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$ 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 * ------ 42267450Sjhb * RSDP -> 0xf2400 (36 bytes fixed) 43270159Sgrehan * RSDT -> 0xf2440 (36 bytes + 4*7 table addrs, 4 used) 44270159Sgrehan * XSDT -> 0xf2480 (36 bytes + 8*7 table addrs, 4 used) 45267450Sjhb * MADT -> 0xf2500 (depends on #CPUs) 46267450Sjhb * FADT -> 0xf2600 (268 bytes) 47267450Sjhb * HPET -> 0xf2740 (56 bytes) 48270159Sgrehan * MCFG -> 0xf2780 (60 bytes) 49270159Sgrehan * FACS -> 0xf27C0 (64 bytes) 50267450Sjhb * DSDT -> 0xf2800 (variable - can go up to 0x100000) 51243327Sgrehan */ 52243327Sgrehan 53243327Sgrehan#include <sys/cdefs.h> 54243327Sgrehan__FBSDID("$FreeBSD$"); 55243327Sgrehan 56243327Sgrehan#include <sys/param.h> 57243327Sgrehan#include <sys/errno.h> 58243327Sgrehan#include <sys/stat.h> 59243327Sgrehan 60243327Sgrehan#include <paths.h> 61261265Sjhb#include <stdarg.h> 62243327Sgrehan#include <stdio.h> 63243327Sgrehan#include <stdlib.h> 64243327Sgrehan#include <string.h> 65243327Sgrehan#include <unistd.h> 66243327Sgrehan 67261088Sjhb#include <machine/vmm.h> 68261088Sjhb#include <vmmapi.h> 69261088Sjhb 70244167Sgrehan#include "bhyverun.h" 71243327Sgrehan#include "acpi.h" 72261265Sjhb#include "pci_emul.h" 73243327Sgrehan 74243327Sgrehan/* 75243327Sgrehan * Define the base address of the ACPI tables, and the offsets to 76243327Sgrehan * the individual tables 77243327Sgrehan */ 78267450Sjhb#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 83261088Sjhb#define HPET_OFFSET 0x340 84270159Sgrehan#define MCFG_OFFSET 0x380 85270159Sgrehan#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; 96261088Sjhbstatic 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 105261265Sjhb/* 106261265Sjhb * State for dsdt_line(), dsdt_indent(), and dsdt_unindent(). 107261265Sjhb */ 108261265Sjhbstatic FILE *dsdt_fp; 109261265Sjhbstatic int dsdt_indent_level; 110261265Sjhbstatic int dsdt_error; 111261265Sjhb 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 176261088Sjhb /* 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); 181261088Sjhb EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : %08X\n", 182261088Sjhb basl_acpi_base + HPET_OFFSET); 183270159Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 3 : %08X\n", 184270159Sgrehan 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 216261088Sjhb /* 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); 221261088Sjhb EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : 00000000%08X\n", 222261088Sjhb basl_acpi_base + HPET_OFFSET); 223270159Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 3 : 00000000%08X\n", 224270159Sgrehan 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 275261088Sjhb /* 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 */ 279259301Sgrehan 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 285259301Sgrehan /* 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"); 289259301Sgrehan EFPRINTF(fp, "[0001]\t\tSource : 00\n"); 290259301Sgrehan EFPRINTF(fp, "[0004]\t\tInterrupt : 00000002\n"); 291259301Sgrehan EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n"); 292259301Sgrehan EFPRINTF(fp, "\t\t\tPolarity : 1\n"); 293259301Sgrehan EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n"); 294259301Sgrehan EFPRINTF(fp, "\n"); 295259301Sgrehan 296259301Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n"); 297259301Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 0A\n"); 298259301Sgrehan EFPRINTF(fp, "[0001]\t\tBus : 00\n"); 299261090Sjhb EFPRINTF(fp, "[0001]\t\tSource : %02X\n", SCI_INT); 300261090Sjhb EFPRINTF(fp, "[0004]\t\tInterrupt : %08X\n", SCI_INT); 301243327Sgrehan EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0000\n"); 302261090Sjhb EFPRINTF(fp, "\t\t\tPolarity : 3\n"); 303261090Sjhb EFPRINTF(fp, "\t\t\tTrigger Mode : 3\n"); 304243327Sgrehan EFPRINTF(fp, "\n"); 305243327Sgrehan 306262350Sjhb /* Local APIC NMI is connected to LINT 1 on all CPUs */ 307262350Sjhb EFPRINTF(fp, "[0001]\t\tSubtable Type : 04\n"); 308262350Sjhb EFPRINTF(fp, "[0001]\t\tLength : 06\n"); 309262350Sjhb EFPRINTF(fp, "[0001]\t\tProcessorId : FF\n"); 310262350Sjhb EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n"); 311262350Sjhb EFPRINTF(fp, "\t\t\tPolarity : 1\n"); 312262350Sjhb EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n"); 313262350Sjhb EFPRINTF(fp, "[0001]\t\tInterrupt : 01\n"); 314262350Sjhb EFPRINTF(fp, "\n"); 315262350Sjhb 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); 350261090Sjhb EFPRINTF(fp, "[0001]\t\tModel : 01\n"); 351243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM Profile : 00 [Unspecified]\n"); 352261090Sjhb EFPRINTF(fp, "[0002]\t\tSCI Interrupt : %04X\n", 353261090Sjhb SCI_INT); 354261090Sjhb EFPRINTF(fp, "[0004]\t\tSMI Command Port : %08X\n", 355261090Sjhb SMI_CMD); 356261090Sjhb EFPRINTF(fp, "[0001]\t\tACPI Enable Value : %02X\n", 357261090Sjhb BHYVE_ACPI_ENABLE); 358261090Sjhb EFPRINTF(fp, "[0001]\t\tACPI Disable Value : %02X\n", 359261090Sjhb BHYVE_ACPI_DISABLE); 360243327Sgrehan EFPRINTF(fp, "[0001]\t\tS4BIOS Command : 00\n"); 361243327Sgrehan EFPRINTF(fp, "[0001]\t\tP-State Control : 00\n"); 362261090Sjhb EFPRINTF(fp, "[0004]\t\tPM1A Event Block Address : %08X\n", 363261090Sjhb PM1A_EVT_ADDR); 364243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM1B Event Block Address : 00000000\n"); 365261090Sjhb EFPRINTF(fp, "[0004]\t\tPM1A Control Block Address : %08X\n", 366261090Sjhb 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", 370261090Sjhb 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"); 389243327Sgrehan EFPRINTF(fp, "[0001]\t\tRTC Century Index : 00\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"); 401261090Sjhb EFPRINTF(fp, "\t\t\tAll CPUs support C1 (V1) : 1\n"); 402243327Sgrehan EFPRINTF(fp, "\t\t\tC2 works on MP system (V1) : 0\n"); 403261090Sjhb 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"); 409261090Sjhb 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"); 429261090Sjhb EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000CF9\n"); 430243327Sgrehan EFPRINTF(fp, "\n"); 431243327Sgrehan 432261090Sjhb EFPRINTF(fp, "[0001]\t\tValue to cause reset : 06\n"); 433243327Sgrehan EFPRINTF(fp, "[0003]\t\tReserved : 000000\n"); 434243327Sgrehan EFPRINTF(fp, "[0008]\t\tFACS Address : 00000000%08X\n", 435243327Sgrehan basl_acpi_base + FACS_OFFSET); 436243327Sgrehan EFPRINTF(fp, "[0008]\t\tDSDT Address : 00000000%08X\n", 437243327Sgrehan basl_acpi_base + DSDT_OFFSET); 438243327Sgrehan EFPRINTF(fp, 439243327Sgrehan "[0012]\t\tPM1A Event Block : [Generic Address Structure]\n"); 440243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 441243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 20\n"); 442243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 443243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n"); 444261090Sjhb EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n", 445261090Sjhb PM1A_EVT_ADDR); 446243327Sgrehan EFPRINTF(fp, "\n"); 447243327Sgrehan 448243327Sgrehan EFPRINTF(fp, 449243327Sgrehan "[0012]\t\tPM1B Event Block : [Generic Address Structure]\n"); 450243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 451243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 452243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 453243327Sgrehan EFPRINTF(fp, 454243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 455243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 456243327Sgrehan EFPRINTF(fp, "\n"); 457243327Sgrehan 458243327Sgrehan EFPRINTF(fp, 459243327Sgrehan "[0012]\t\tPM1A Control Block : [Generic Address Structure]\n"); 460243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 461243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 10\n"); 462243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 463243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n"); 464261090Sjhb EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n", 465261090Sjhb PM1A_CNT_ADDR); 466243327Sgrehan EFPRINTF(fp, "\n"); 467243327Sgrehan 468243327Sgrehan EFPRINTF(fp, 469243327Sgrehan "[0012]\t\tPM1B Control Block : [Generic Address Structure]\n"); 470243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 471243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 472243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 473243327Sgrehan EFPRINTF(fp, 474243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 475243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 476243327Sgrehan EFPRINTF(fp, "\n"); 477243327Sgrehan 478243327Sgrehan EFPRINTF(fp, 479243327Sgrehan "[0012]\t\tPM2 Control Block : [Generic Address Structure]\n"); 480243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 481243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 482243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 483243327Sgrehan EFPRINTF(fp, 484243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 485243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 486243327Sgrehan EFPRINTF(fp, "\n"); 487243327Sgrehan 488243327Sgrehan /* Valid for bhyve */ 489243327Sgrehan EFPRINTF(fp, 490243327Sgrehan "[0012]\t\tPM Timer Block : [Generic Address Structure]\n"); 491243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 492243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 32\n"); 493243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 494243327Sgrehan EFPRINTF(fp, 495243327Sgrehan "[0001]\t\tEncoded Access Width : 03 [DWord Access:32]\n"); 496243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n", 497261090Sjhb IO_PMTMR); 498243327Sgrehan EFPRINTF(fp, "\n"); 499243327Sgrehan 500243327Sgrehan EFPRINTF(fp, "[0012]\t\tGPE0 Block : [Generic Address Structure]\n"); 501243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 502243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 80\n"); 503243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 504243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 505243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 506243327Sgrehan EFPRINTF(fp, "\n"); 507243327Sgrehan 508243327Sgrehan EFPRINTF(fp, "[0012]\t\tGPE1 Block : [Generic Address Structure]\n"); 509243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 510243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 511243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 512243327Sgrehan EFPRINTF(fp, 513243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 514243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 515243327Sgrehan EFPRINTF(fp, "\n"); 516243327Sgrehan 517243327Sgrehan EFPRINTF(fp, 518243327Sgrehan "[0012]\t\tSleep Control Register : [Generic Address Structure]\n"); 519243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 520243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 521243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 522243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 523243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 524243327Sgrehan EFPRINTF(fp, "\n"); 525243327Sgrehan 526243327Sgrehan EFPRINTF(fp, 527243327Sgrehan "[0012]\t\tSleep Status Register : [Generic Address Structure]\n"); 528243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 529243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 530243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 531243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 532243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 533243327Sgrehan 534243327Sgrehan EFFLUSH(fp); 535243327Sgrehan 536243327Sgrehan return (0); 537243327Sgrehan 538243327Sgrehanerr_exit: 539243327Sgrehan return (errno); 540243327Sgrehan} 541243327Sgrehan 542243327Sgrehanstatic int 543261088Sjhbbasl_fwrite_hpet(FILE *fp) 544261088Sjhb{ 545261088Sjhb int err; 546261088Sjhb 547261088Sjhb err = 0; 548261088Sjhb 549261088Sjhb EFPRINTF(fp, "/*\n"); 550261088Sjhb EFPRINTF(fp, " * bhyve HPET template\n"); 551261088Sjhb EFPRINTF(fp, " */\n"); 552261088Sjhb EFPRINTF(fp, "[0004]\t\tSignature : \"HPET\"\n"); 553261088Sjhb EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 554261088Sjhb EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 555261088Sjhb EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 556261088Sjhb EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 557261088Sjhb EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVHPET \"\n"); 558261088Sjhb EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 559261088Sjhb 560261088Sjhb /* iasl will fill in the compiler ID/revision fields */ 561261088Sjhb EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 562261088Sjhb EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 563261088Sjhb EFPRINTF(fp, "\n"); 564261088Sjhb 565261088Sjhb EFPRINTF(fp, "[0004]\t\tTimer Block ID : %08X\n", hpet_capabilities); 566261088Sjhb EFPRINTF(fp, 567261088Sjhb "[0012]\t\tTimer Block Register : [Generic Address Structure]\n"); 568261088Sjhb EFPRINTF(fp, "[0001]\t\tSpace ID : 00 [SystemMemory]\n"); 569261088Sjhb EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 570261088Sjhb EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 571261088Sjhb EFPRINTF(fp, 572261088Sjhb "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 573261088Sjhb EFPRINTF(fp, "[0008]\t\tAddress : 00000000FED00000\n"); 574261088Sjhb EFPRINTF(fp, "\n"); 575261088Sjhb 576261088Sjhb EFPRINTF(fp, "[0001]\t\tHPET Number : 00\n"); 577261088Sjhb EFPRINTF(fp, "[0002]\t\tMinimum Clock Ticks : 0000\n"); 578261088Sjhb EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n"); 579261088Sjhb EFPRINTF(fp, "\t\t\t4K Page Protect : 1\n"); 580261088Sjhb EFPRINTF(fp, "\t\t\t64K Page Protect : 0\n"); 581261088Sjhb EFPRINTF(fp, "\n"); 582261088Sjhb 583261088Sjhb EFFLUSH(fp); 584261088Sjhb 585261088Sjhb return (0); 586261088Sjhb 587261088Sjhberr_exit: 588261088Sjhb return (errno); 589261088Sjhb} 590261088Sjhb 591261088Sjhbstatic int 592270159Sgrehanbasl_fwrite_mcfg(FILE *fp) 593270159Sgrehan{ 594270159Sgrehan int err = 0; 595270159Sgrehan 596270159Sgrehan EFPRINTF(fp, "/*\n"); 597270159Sgrehan EFPRINTF(fp, " * bhyve MCFG template\n"); 598270159Sgrehan EFPRINTF(fp, " */\n"); 599270159Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"MCFG\"\n"); 600270159Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 601270159Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 602270159Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 603270159Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 604270159Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVMCFG \"\n"); 605270159Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 606270159Sgrehan 607270159Sgrehan /* iasl will fill in the compiler ID/revision fields */ 608270159Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 609270159Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 610270159Sgrehan EFPRINTF(fp, "[0008]\t\tReserved : 0\n"); 611270159Sgrehan EFPRINTF(fp, "\n"); 612270159Sgrehan 613270159Sgrehan EFPRINTF(fp, "[0008]\t\tBase Address : %016lX\n", pci_ecfg_base()); 614270159Sgrehan EFPRINTF(fp, "[0002]\t\tSegment Group: 0000\n"); 615270159Sgrehan EFPRINTF(fp, "[0001]\t\tStart Bus: 00\n"); 616270159Sgrehan EFPRINTF(fp, "[0001]\t\tEnd Bus: FF\n"); 617270159Sgrehan EFPRINTF(fp, "[0004]\t\tReserved : 0\n"); 618270159Sgrehan EFFLUSH(fp); 619270159Sgrehan return (0); 620270159Sgrehanerr_exit: 621270159Sgrehan return (errno); 622270159Sgrehan} 623270159Sgrehan 624270159Sgrehanstatic int 625243327Sgrehanbasl_fwrite_facs(FILE *fp) 626243327Sgrehan{ 627243327Sgrehan int err; 628243327Sgrehan 629243327Sgrehan err = 0; 630243327Sgrehan 631243327Sgrehan EFPRINTF(fp, "/*\n"); 632243327Sgrehan EFPRINTF(fp, " * bhyve FACS template\n"); 633243327Sgrehan EFPRINTF(fp, " */\n"); 634243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"FACS\"\n"); 635243327Sgrehan EFPRINTF(fp, "[0004]\t\tLength : 00000040\n"); 636243327Sgrehan EFPRINTF(fp, "[0004]\t\tHardware Signature : 00000000\n"); 637243327Sgrehan EFPRINTF(fp, "[0004]\t\t32 Firmware Waking Vector : 00000000\n"); 638243327Sgrehan EFPRINTF(fp, "[0004]\t\tGlobal Lock : 00000000\n"); 639243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n"); 640243327Sgrehan EFPRINTF(fp, "\t\t\tS4BIOS Support Present : 0\n"); 641243327Sgrehan EFPRINTF(fp, "\t\t\t64-bit Wake Supported (V2) : 0\n"); 642243327Sgrehan EFPRINTF(fp, 643243327Sgrehan "[0008]\t\t64 Firmware Waking Vector : 0000000000000000\n"); 644243327Sgrehan EFPRINTF(fp, "[0001]\t\tVersion : 02\n"); 645243327Sgrehan EFPRINTF(fp, "[0003]\t\tReserved : 000000\n"); 646243327Sgrehan EFPRINTF(fp, "[0004]\t\tOspmFlags (decoded below) : 00000000\n"); 647243327Sgrehan EFPRINTF(fp, "\t\t\t64-bit Wake Env Required (V2) : 0\n"); 648243327Sgrehan 649243327Sgrehan EFFLUSH(fp); 650243327Sgrehan 651243327Sgrehan return (0); 652243327Sgrehan 653243327Sgrehanerr_exit: 654243327Sgrehan return (errno); 655243327Sgrehan} 656243327Sgrehan 657261265Sjhb/* 658261265Sjhb * Helper routines for writing to the DSDT from other modules. 659261265Sjhb */ 660261265Sjhbvoid 661261265Sjhbdsdt_line(const char *fmt, ...) 662261265Sjhb{ 663261265Sjhb va_list ap; 664261265Sjhb int err; 665261265Sjhb 666261265Sjhb if (dsdt_error != 0) 667261265Sjhb return; 668261265Sjhb 669261265Sjhb if (strcmp(fmt, "") != 0) { 670261265Sjhb if (dsdt_indent_level != 0) 671261265Sjhb EFPRINTF(dsdt_fp, "%*c", dsdt_indent_level * 2, ' '); 672261265Sjhb va_start(ap, fmt); 673261265Sjhb if (vfprintf(dsdt_fp, fmt, ap) < 0) 674261265Sjhb goto err_exit; 675261265Sjhb va_end(ap); 676261265Sjhb } 677261265Sjhb EFPRINTF(dsdt_fp, "\n"); 678261265Sjhb return; 679261265Sjhb 680261265Sjhberr_exit: 681261265Sjhb dsdt_error = errno; 682261265Sjhb} 683261265Sjhb 684261265Sjhbvoid 685261265Sjhbdsdt_indent(int levels) 686261265Sjhb{ 687261265Sjhb 688261265Sjhb dsdt_indent_level += levels; 689261265Sjhb assert(dsdt_indent_level >= 0); 690261265Sjhb} 691261265Sjhb 692261265Sjhbvoid 693261265Sjhbdsdt_unindent(int levels) 694261265Sjhb{ 695261265Sjhb 696261265Sjhb assert(dsdt_indent_level >= levels); 697261265Sjhb dsdt_indent_level -= levels; 698261265Sjhb} 699261265Sjhb 700261265Sjhbvoid 701261265Sjhbdsdt_fixed_ioport(uint16_t iobase, uint16_t length) 702261265Sjhb{ 703261265Sjhb 704261265Sjhb dsdt_line("IO (Decode16,"); 705261265Sjhb dsdt_line(" 0x%04X, // Range Minimum", iobase); 706261265Sjhb dsdt_line(" 0x%04X, // Range Maximum", iobase); 707261265Sjhb dsdt_line(" 0x01, // Alignment"); 708261265Sjhb dsdt_line(" 0x%02X, // Length", length); 709261265Sjhb dsdt_line(" )"); 710261265Sjhb} 711261265Sjhb 712261265Sjhbvoid 713261265Sjhbdsdt_fixed_irq(uint8_t irq) 714261265Sjhb{ 715261265Sjhb 716261265Sjhb dsdt_line("IRQNoFlags ()"); 717261265Sjhb dsdt_line(" {%d}", irq); 718261265Sjhb} 719261265Sjhb 720261265Sjhbvoid 721261265Sjhbdsdt_fixed_mem32(uint32_t base, uint32_t length) 722261265Sjhb{ 723261265Sjhb 724261265Sjhb dsdt_line("Memory32Fixed (ReadWrite,"); 725261265Sjhb dsdt_line(" 0x%08X, // Address Base", base); 726261265Sjhb dsdt_line(" 0x%08X, // Address Length", length); 727261265Sjhb dsdt_line(" )"); 728261265Sjhb} 729261265Sjhb 730243327Sgrehanstatic int 731243327Sgrehanbasl_fwrite_dsdt(FILE *fp) 732243327Sgrehan{ 733243327Sgrehan int err; 734243327Sgrehan 735243327Sgrehan err = 0; 736261265Sjhb dsdt_fp = fp; 737261265Sjhb dsdt_error = 0; 738261265Sjhb dsdt_indent_level = 0; 739243327Sgrehan 740261265Sjhb dsdt_line("/*"); 741261265Sjhb dsdt_line(" * bhyve DSDT template"); 742261265Sjhb dsdt_line(" */"); 743261265Sjhb dsdt_line("DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2," 744261265Sjhb "\"BHYVE \", \"BVDSDT \", 0x00000001)"); 745261265Sjhb dsdt_line("{"); 746268972Sjhb dsdt_line(" Name (_S5, Package ()"); 747261265Sjhb dsdt_line(" {"); 748261265Sjhb dsdt_line(" 0x05,"); 749261265Sjhb dsdt_line(" Zero,"); 750261265Sjhb dsdt_line(" })"); 751261088Sjhb 752261265Sjhb pci_write_dsdt(); 753261088Sjhb 754261265Sjhb dsdt_line(""); 755268887Sjhb dsdt_line(" Scope (_SB.PC00)"); 756261265Sjhb dsdt_line(" {"); 757261265Sjhb dsdt_line(" Device (HPET)"); 758261265Sjhb dsdt_line(" {"); 759261265Sjhb dsdt_line(" Name (_HID, EISAID(\"PNP0103\"))"); 760261265Sjhb dsdt_line(" Name (_UID, 0)"); 761261265Sjhb dsdt_line(" Name (_CRS, ResourceTemplate ()"); 762261265Sjhb dsdt_line(" {"); 763261265Sjhb dsdt_indent(4); 764261265Sjhb dsdt_fixed_mem32(0xFED00000, 0x400); 765261265Sjhb dsdt_unindent(4); 766261265Sjhb dsdt_line(" })"); 767261265Sjhb dsdt_line(" }"); 768261265Sjhb dsdt_line(" }"); 769261265Sjhb dsdt_line("}"); 770243327Sgrehan 771261265Sjhb if (dsdt_error != 0) 772261265Sjhb return (dsdt_error); 773261265Sjhb 774243327Sgrehan EFFLUSH(fp); 775243327Sgrehan 776243327Sgrehan return (0); 777243327Sgrehan 778243327Sgrehanerr_exit: 779243327Sgrehan return (errno); 780243327Sgrehan} 781243327Sgrehan 782243327Sgrehanstatic int 783243327Sgrehanbasl_open(struct basl_fio *bf, int suffix) 784243327Sgrehan{ 785243327Sgrehan int err; 786243327Sgrehan 787243327Sgrehan err = 0; 788243327Sgrehan 789243327Sgrehan if (suffix) { 790243327Sgrehan strncpy(bf->f_name, basl_stemplate, MAXPATHLEN); 791243327Sgrehan bf->fd = mkstemps(bf->f_name, strlen(BHYVE_ASL_SUFFIX)); 792243327Sgrehan } else { 793243327Sgrehan strncpy(bf->f_name, basl_template, MAXPATHLEN); 794243327Sgrehan bf->fd = mkstemp(bf->f_name); 795243327Sgrehan } 796243327Sgrehan 797243327Sgrehan if (bf->fd > 0) { 798243327Sgrehan bf->fp = fdopen(bf->fd, "w+"); 799243327Sgrehan if (bf->fp == NULL) { 800243327Sgrehan unlink(bf->f_name); 801243327Sgrehan close(bf->fd); 802243327Sgrehan } 803243327Sgrehan } else { 804243327Sgrehan err = 1; 805243327Sgrehan } 806243327Sgrehan 807243327Sgrehan return (err); 808243327Sgrehan} 809243327Sgrehan 810243327Sgrehanstatic void 811243327Sgrehanbasl_close(struct basl_fio *bf) 812243327Sgrehan{ 813243327Sgrehan 814243327Sgrehan if (!basl_keep_temps) 815243327Sgrehan unlink(bf->f_name); 816243327Sgrehan fclose(bf->fp); 817243327Sgrehan} 818243327Sgrehan 819243327Sgrehanstatic int 820243327Sgrehanbasl_start(struct basl_fio *in, struct basl_fio *out) 821243327Sgrehan{ 822243327Sgrehan int err; 823243327Sgrehan 824243327Sgrehan err = basl_open(in, 0); 825243327Sgrehan if (!err) { 826243327Sgrehan err = basl_open(out, 1); 827243327Sgrehan if (err) { 828243327Sgrehan basl_close(in); 829243327Sgrehan } 830243327Sgrehan } 831243327Sgrehan 832243327Sgrehan return (err); 833243327Sgrehan} 834243327Sgrehan 835243327Sgrehanstatic void 836243327Sgrehanbasl_end(struct basl_fio *in, struct basl_fio *out) 837243327Sgrehan{ 838243327Sgrehan 839243327Sgrehan basl_close(in); 840243327Sgrehan basl_close(out); 841243327Sgrehan} 842243327Sgrehan 843243327Sgrehanstatic int 844248477Sneelbasl_load(struct vmctx *ctx, int fd, uint64_t off) 845243327Sgrehan{ 846248477Sneel struct stat sb; 847247523Sneel void *gaddr; 848243327Sgrehan 849248477Sneel if (fstat(fd, &sb) < 0) 850248477Sneel return (errno); 851248477Sneel 852248477Sneel gaddr = paddr_guest2host(ctx, basl_acpi_base + off, sb.st_size); 853248477Sneel if (gaddr == NULL) 854248477Sneel return (EFAULT); 855243327Sgrehan 856248477Sneel if (read(fd, gaddr, sb.st_size) < 0) 857248477Sneel return (errno); 858248477Sneel 859248477Sneel return (0); 860243327Sgrehan} 861243327Sgrehan 862243327Sgrehanstatic int 863248477Sneelbasl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *), uint64_t offset) 864243327Sgrehan{ 865243327Sgrehan struct basl_fio io[2]; 866243327Sgrehan static char iaslbuf[3*MAXPATHLEN + 10]; 867243327Sgrehan char *fmt; 868243327Sgrehan int err; 869243327Sgrehan 870243327Sgrehan err = basl_start(&io[0], &io[1]); 871243327Sgrehan if (!err) { 872243327Sgrehan err = (*fwrite_section)(io[0].fp); 873243327Sgrehan 874243327Sgrehan if (!err) { 875243327Sgrehan /* 876243327Sgrehan * iasl sends the results of the compilation to 877243327Sgrehan * stdout. Shut this down by using the shell to 878243327Sgrehan * redirect stdout to /dev/null, unless the user 879243327Sgrehan * has requested verbose output for debugging 880243327Sgrehan * purposes 881243327Sgrehan */ 882243327Sgrehan fmt = basl_verbose_iasl ? 883243327Sgrehan "%s -p %s %s" : 884243327Sgrehan "/bin/sh -c \"%s -p %s %s\" 1> /dev/null"; 885243327Sgrehan 886243327Sgrehan snprintf(iaslbuf, sizeof(iaslbuf), 887243327Sgrehan fmt, 888243327Sgrehan BHYVE_ASL_COMPILER, 889243327Sgrehan io[1].f_name, io[0].f_name); 890243327Sgrehan err = system(iaslbuf); 891243327Sgrehan 892243327Sgrehan if (!err) { 893243327Sgrehan /* 894243327Sgrehan * Copy the aml output file into guest 895243327Sgrehan * memory at the specified location 896243327Sgrehan */ 897248477Sneel err = basl_load(ctx, io[1].fd, offset); 898243327Sgrehan } 899243327Sgrehan } 900243327Sgrehan basl_end(&io[0], &io[1]); 901243327Sgrehan } 902243327Sgrehan 903243327Sgrehan return (err); 904243327Sgrehan} 905243327Sgrehan 906243327Sgrehanstatic int 907243327Sgrehanbasl_make_templates(void) 908243327Sgrehan{ 909243327Sgrehan const char *tmpdir; 910243327Sgrehan int err; 911243327Sgrehan int len; 912243327Sgrehan 913243327Sgrehan err = 0; 914243327Sgrehan 915243327Sgrehan /* 916243327Sgrehan * 917243327Sgrehan */ 918243327Sgrehan if ((tmpdir = getenv("BHYVE_TMPDIR")) == NULL || *tmpdir == '\0' || 919243327Sgrehan (tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') { 920243327Sgrehan tmpdir = _PATH_TMP; 921243327Sgrehan } 922243327Sgrehan 923243327Sgrehan len = strlen(tmpdir); 924243327Sgrehan 925243327Sgrehan if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1) < MAXPATHLEN) { 926243327Sgrehan strcpy(basl_template, tmpdir); 927243327Sgrehan while (len > 0 && basl_template[len - 1] == '/') 928243327Sgrehan len--; 929243327Sgrehan basl_template[len] = '/'; 930243327Sgrehan strcpy(&basl_template[len + 1], BHYVE_ASL_TEMPLATE); 931243327Sgrehan } else 932243327Sgrehan err = E2BIG; 933243327Sgrehan 934243327Sgrehan if (!err) { 935243327Sgrehan /* 936243327Sgrehan * len has been intialized (and maybe adjusted) above 937243327Sgrehan */ 938243327Sgrehan if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1 + 939243327Sgrehan sizeof(BHYVE_ASL_SUFFIX)) < MAXPATHLEN) { 940243327Sgrehan strcpy(basl_stemplate, tmpdir); 941243327Sgrehan basl_stemplate[len] = '/'; 942243327Sgrehan strcpy(&basl_stemplate[len + 1], BHYVE_ASL_TEMPLATE); 943243327Sgrehan len = strlen(basl_stemplate); 944243327Sgrehan strcpy(&basl_stemplate[len], BHYVE_ASL_SUFFIX); 945243327Sgrehan } else 946243327Sgrehan err = E2BIG; 947243327Sgrehan } 948243327Sgrehan 949243327Sgrehan return (err); 950243327Sgrehan} 951243327Sgrehan 952243327Sgrehanstatic struct { 953243327Sgrehan int (*wsect)(FILE *fp); 954243327Sgrehan uint64_t offset; 955243327Sgrehan} basl_ftables[] = 956243327Sgrehan{ 957243327Sgrehan { basl_fwrite_rsdp, 0}, 958243327Sgrehan { basl_fwrite_rsdt, RSDT_OFFSET }, 959243704Sgrehan { basl_fwrite_xsdt, XSDT_OFFSET }, 960243327Sgrehan { basl_fwrite_madt, MADT_OFFSET }, 961243327Sgrehan { basl_fwrite_fadt, FADT_OFFSET }, 962261088Sjhb { basl_fwrite_hpet, HPET_OFFSET }, 963270159Sgrehan { basl_fwrite_mcfg, MCFG_OFFSET }, 964243327Sgrehan { basl_fwrite_facs, FACS_OFFSET }, 965243327Sgrehan { basl_fwrite_dsdt, DSDT_OFFSET }, 966243327Sgrehan { NULL } 967243327Sgrehan}; 968243327Sgrehan 969243327Sgrehanint 970259301Sgrehanacpi_build(struct vmctx *ctx, int ncpu) 971243327Sgrehan{ 972243327Sgrehan int err; 973243327Sgrehan int i; 974243327Sgrehan 975243327Sgrehan basl_ncpu = ncpu; 976243327Sgrehan 977261088Sjhb err = vm_get_hpet_capabilities(ctx, &hpet_capabilities); 978261088Sjhb if (err != 0) 979261088Sjhb return (err); 980261088Sjhb 981243327Sgrehan /* 982243327Sgrehan * For debug, allow the user to have iasl compiler output sent 983243327Sgrehan * to stdout rather than /dev/null 984243327Sgrehan */ 985243327Sgrehan if (getenv("BHYVE_ACPI_VERBOSE_IASL")) 986243327Sgrehan basl_verbose_iasl = 1; 987243327Sgrehan 988243327Sgrehan /* 989243327Sgrehan * Allow the user to keep the generated ASL files for debugging 990243327Sgrehan * instead of deleting them following use 991243327Sgrehan */ 992243327Sgrehan if (getenv("BHYVE_ACPI_KEEPTMPS")) 993243327Sgrehan basl_keep_temps = 1; 994243327Sgrehan 995243327Sgrehan i = 0; 996243327Sgrehan err = basl_make_templates(); 997243327Sgrehan 998243327Sgrehan /* 999243327Sgrehan * Run through all the ASL files, compiling them and 1000243327Sgrehan * copying them into guest memory 1001243327Sgrehan */ 1002243327Sgrehan while (!err && basl_ftables[i].wsect != NULL) { 1003248477Sneel err = basl_compile(ctx, basl_ftables[i].wsect, 1004243327Sgrehan basl_ftables[i].offset); 1005243327Sgrehan i++; 1006243327Sgrehan } 1007243327Sgrehan 1008243327Sgrehan return (err); 1009243327Sgrehan} 1010