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 * ------ 42243327Sgrehan * RSDP -> 0xf0400 (36 bytes fixed) 43243704Sgrehan * RSDT -> 0xf0440 (36 bytes + 4*N table addrs, 2 used) 44243704Sgrehan * XSDT -> 0xf0480 (36 bytes + 8*N table addrs, 2 used) 45243704Sgrehan * MADT -> 0xf0500 (depends on #CPUs) 46243704Sgrehan * FADT -> 0xf0600 (268 bytes) 47243704Sgrehan * FACS -> 0xf0780 (64 bytes) 48243704Sgrehan * DSDT -> 0xf0800 (variable - can go up to 0x100000) 49243327Sgrehan */ 50243327Sgrehan 51243327Sgrehan#include <sys/cdefs.h> 52243327Sgrehan__FBSDID("$FreeBSD$"); 53243327Sgrehan 54243327Sgrehan#include <sys/param.h> 55243327Sgrehan#include <sys/errno.h> 56243327Sgrehan#include <sys/stat.h> 57243327Sgrehan 58243327Sgrehan#include <paths.h> 59243327Sgrehan#include <stdio.h> 60243327Sgrehan#include <stdlib.h> 61243327Sgrehan#include <string.h> 62243327Sgrehan#include <unistd.h> 63243327Sgrehan 64244167Sgrehan#include "bhyverun.h" 65243327Sgrehan#include "acpi.h" 66243327Sgrehan 67243327Sgrehan/* 68243327Sgrehan * Define the base address of the ACPI tables, and the offsets to 69243327Sgrehan * the individual tables 70243327Sgrehan */ 71243327Sgrehan#define BHYVE_ACPI_BASE 0xf0400 72243327Sgrehan#define RSDT_OFFSET 0x040 73243704Sgrehan#define XSDT_OFFSET 0x080 74243704Sgrehan#define MADT_OFFSET 0x100 75243327Sgrehan#define FADT_OFFSET 0x200 76243327Sgrehan#define FACS_OFFSET 0x380 77243327Sgrehan#define DSDT_OFFSET 0x400 78243327Sgrehan 79243327Sgrehan#define BHYVE_ASL_TEMPLATE "bhyve.XXXXXXX" 80243327Sgrehan#define BHYVE_ASL_SUFFIX ".aml" 81243327Sgrehan#define BHYVE_ASL_COMPILER "/usr/sbin/iasl" 82243327Sgrehan 83243327Sgrehan#define BHYVE_PM_TIMER_ADDR 0x408 84243327Sgrehan 85243327Sgrehanstatic int basl_keep_temps; 86243327Sgrehanstatic int basl_verbose_iasl; 87243327Sgrehanstatic int basl_ncpu; 88243327Sgrehanstatic uint32_t basl_acpi_base = BHYVE_ACPI_BASE; 89243327Sgrehan 90243327Sgrehan/* 91243327Sgrehan * Contains the full pathname of the template to be passed 92243327Sgrehan * to mkstemp/mktemps(3) 93243327Sgrehan */ 94243327Sgrehanstatic char basl_template[MAXPATHLEN]; 95243327Sgrehanstatic char basl_stemplate[MAXPATHLEN]; 96243327Sgrehan 97243327Sgrehanstruct basl_fio { 98243327Sgrehan int fd; 99243327Sgrehan FILE *fp; 100243327Sgrehan char f_name[MAXPATHLEN]; 101243327Sgrehan}; 102243327Sgrehan 103243327Sgrehan#define EFPRINTF(...) \ 104243327Sgrehan err = fprintf(__VA_ARGS__); if (err < 0) goto err_exit; 105243327Sgrehan 106243327Sgrehan#define EFFLUSH(x) \ 107243327Sgrehan err = fflush(x); if (err != 0) goto err_exit; 108243327Sgrehan 109243327Sgrehanstatic int 110243327Sgrehanbasl_fwrite_rsdp(FILE *fp) 111243327Sgrehan{ 112243327Sgrehan int err; 113243327Sgrehan 114243327Sgrehan err = 0; 115243327Sgrehan 116243327Sgrehan EFPRINTF(fp, "/*\n"); 117243327Sgrehan EFPRINTF(fp, " * bhyve RSDP template\n"); 118243327Sgrehan EFPRINTF(fp, " */\n"); 119243327Sgrehan EFPRINTF(fp, "[0008]\t\tSignature : \"RSD PTR \"\n"); 120243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 43\n"); 121243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 122243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 02\n"); 123243327Sgrehan EFPRINTF(fp, "[0004]\t\tRSDT Address : %08X\n", 124243327Sgrehan basl_acpi_base + RSDT_OFFSET); 125243327Sgrehan EFPRINTF(fp, "[0004]\t\tLength : 00000024\n"); 126243704Sgrehan EFPRINTF(fp, "[0008]\t\tXSDT Address : 00000000%08X\n", 127243704Sgrehan basl_acpi_base + XSDT_OFFSET); 128243327Sgrehan EFPRINTF(fp, "[0001]\t\tExtended Checksum : 00\n"); 129243327Sgrehan EFPRINTF(fp, "[0003]\t\tReserved : 000000\n"); 130243327Sgrehan 131243327Sgrehan EFFLUSH(fp); 132243327Sgrehan 133243327Sgrehan return (0); 134243327Sgrehan 135243327Sgrehanerr_exit: 136243327Sgrehan return (errno); 137243327Sgrehan} 138243327Sgrehan 139243327Sgrehanstatic int 140243327Sgrehanbasl_fwrite_rsdt(FILE *fp) 141243327Sgrehan{ 142243327Sgrehan int err; 143243327Sgrehan 144243327Sgrehan err = 0; 145243327Sgrehan 146243327Sgrehan EFPRINTF(fp, "/*\n"); 147243327Sgrehan EFPRINTF(fp, " * bhyve RSDT template\n"); 148243327Sgrehan EFPRINTF(fp, " */\n"); 149243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"RSDT\"\n"); 150243327Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 151243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 152243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 153243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 154243327Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVRSDT \"\n"); 155243327Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 156243327Sgrehan /* iasl will fill in the compiler ID/revision fields */ 157243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 158243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 159243327Sgrehan EFPRINTF(fp, "\n"); 160243327Sgrehan 161243327Sgrehan /* Add in pointers to the MADT and FADT */ 162243327Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : %08X\n", 163243327Sgrehan basl_acpi_base + MADT_OFFSET); 164243327Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : %08X\n", 165243327Sgrehan basl_acpi_base + FADT_OFFSET); 166243327Sgrehan 167243327Sgrehan EFFLUSH(fp); 168243327Sgrehan 169243327Sgrehan return (0); 170243327Sgrehan 171243327Sgrehanerr_exit: 172243327Sgrehan return (errno); 173243327Sgrehan} 174243327Sgrehan 175243327Sgrehanstatic int 176243704Sgrehanbasl_fwrite_xsdt(FILE *fp) 177243704Sgrehan{ 178243704Sgrehan int err; 179243704Sgrehan 180243704Sgrehan err = 0; 181243704Sgrehan 182243704Sgrehan EFPRINTF(fp, "/*\n"); 183243704Sgrehan EFPRINTF(fp, " * bhyve XSDT template\n"); 184243704Sgrehan EFPRINTF(fp, " */\n"); 185243704Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"XSDT\"\n"); 186243704Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 187243704Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 188243704Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 189243704Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 190243704Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVXSDT \"\n"); 191243704Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 192243704Sgrehan /* iasl will fill in the compiler ID/revision fields */ 193243704Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 194243704Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 195243704Sgrehan EFPRINTF(fp, "\n"); 196243704Sgrehan 197243704Sgrehan /* Add in pointers to the MADT and FADT */ 198243704Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : 00000000%08X\n", 199243704Sgrehan basl_acpi_base + MADT_OFFSET); 200243704Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : 00000000%08X\n", 201243704Sgrehan basl_acpi_base + FADT_OFFSET); 202243704Sgrehan 203243704Sgrehan EFFLUSH(fp); 204243704Sgrehan 205243704Sgrehan return (0); 206243704Sgrehan 207243704Sgrehanerr_exit: 208243704Sgrehan return (errno); 209243704Sgrehan} 210243704Sgrehan 211243704Sgrehanstatic int 212243327Sgrehanbasl_fwrite_madt(FILE *fp) 213243327Sgrehan{ 214243327Sgrehan int err; 215243327Sgrehan int i; 216243327Sgrehan 217243327Sgrehan err = 0; 218243327Sgrehan 219243327Sgrehan EFPRINTF(fp, "/*\n"); 220243327Sgrehan EFPRINTF(fp, " * bhyve MADT template\n"); 221243327Sgrehan EFPRINTF(fp, " */\n"); 222243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"APIC\"\n"); 223243327Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 224243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 225243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 226243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 227243327Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVMADT \"\n"); 228243327Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 229243327Sgrehan 230243327Sgrehan /* iasl will fill in the compiler ID/revision fields */ 231243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 232243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 233243327Sgrehan EFPRINTF(fp, "\n"); 234243327Sgrehan 235243327Sgrehan EFPRINTF(fp, "[0004]\t\tLocal Apic Address : FEE00000\n"); 236243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n"); 237243327Sgrehan EFPRINTF(fp, "\t\t\tPC-AT Compatibility : 1\n"); 238243327Sgrehan EFPRINTF(fp, "\n"); 239243327Sgrehan 240243327Sgrehan /* Add a Processor Local APIC entry for each CPU */ 241243327Sgrehan for (i = 0; i < basl_ncpu; i++) { 242243327Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 00\n"); 243243327Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 08\n"); 244255438Sgrehan /* iasl expects hex values for the proc and apic id's */ 245255438Sgrehan EFPRINTF(fp, "[0001]\t\tProcessor ID : %02x\n", i); 246255438Sgrehan EFPRINTF(fp, "[0001]\t\tLocal Apic ID : %02x\n", i); 247243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n"); 248243327Sgrehan EFPRINTF(fp, "\t\t\tProcessor Enabled : 1\n"); 249243327Sgrehan EFPRINTF(fp, "\n"); 250243327Sgrehan } 251243327Sgrehan 252243327Sgrehan /* Always a single IOAPIC entry, with ID ncpu+1 */ 253243327Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n"); 254243327Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 0C\n"); 255255438Sgrehan /* iasl expects a hex value for the i/o apic id */ 256259496Sgrehan EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", 0); 257243327Sgrehan EFPRINTF(fp, "[0001]\t\tReserved : 00\n"); 258243327Sgrehan EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n"); 259243327Sgrehan EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n"); 260243327Sgrehan EFPRINTF(fp, "\n"); 261243327Sgrehan 262259496Sgrehan /* Legacy IRQ0 is connected to pin 2 of the IOAPIC */ 263243327Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n"); 264243327Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 0A\n"); 265243327Sgrehan EFPRINTF(fp, "[0001]\t\tBus : 00\n"); 266259496Sgrehan EFPRINTF(fp, "[0001]\t\tSource : 00\n"); 267259496Sgrehan EFPRINTF(fp, "[0004]\t\tInterrupt : 00000002\n"); 268259496Sgrehan EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n"); 269259496Sgrehan EFPRINTF(fp, "\t\t\tPolarity : 1\n"); 270259496Sgrehan EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n"); 271259496Sgrehan EFPRINTF(fp, "\n"); 272259496Sgrehan 273259496Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n"); 274259496Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 0A\n"); 275259496Sgrehan EFPRINTF(fp, "[0001]\t\tBus : 00\n"); 276243327Sgrehan EFPRINTF(fp, "[0001]\t\tSource : 09\n"); 277243327Sgrehan EFPRINTF(fp, "[0004]\t\tInterrupt : 00000009\n"); 278243327Sgrehan EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0000\n"); 279243327Sgrehan EFPRINTF(fp, "\t\t\tPolarity : 0\n"); 280243327Sgrehan EFPRINTF(fp, "\t\t\tTrigger Mode : 0\n"); 281243327Sgrehan EFPRINTF(fp, "\n"); 282243327Sgrehan 283243327Sgrehan EFFLUSH(fp); 284243327Sgrehan 285243327Sgrehan return (0); 286243327Sgrehan 287243327Sgrehanerr_exit: 288243327Sgrehan return (errno); 289243327Sgrehan} 290243327Sgrehan 291243327Sgrehanstatic int 292243327Sgrehanbasl_fwrite_fadt(FILE *fp) 293243327Sgrehan{ 294243327Sgrehan int err; 295243327Sgrehan 296243327Sgrehan err = 0; 297243327Sgrehan 298243327Sgrehan EFPRINTF(fp, "/*\n"); 299243327Sgrehan EFPRINTF(fp, " * bhyve FADT template\n"); 300243327Sgrehan EFPRINTF(fp, " */\n"); 301243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"FACP\"\n"); 302243327Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 0000010C\n"); 303243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 05\n"); 304243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 305243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 306243327Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVFACP \"\n"); 307243327Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 308243327Sgrehan /* iasl will fill in the compiler ID/revision fields */ 309243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 310243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 311243327Sgrehan EFPRINTF(fp, "\n"); 312243327Sgrehan 313243327Sgrehan EFPRINTF(fp, "[0004]\t\tFACS Address : %08X\n", 314243327Sgrehan basl_acpi_base + FACS_OFFSET); 315243327Sgrehan EFPRINTF(fp, "[0004]\t\tDSDT Address : %08X\n", 316243327Sgrehan basl_acpi_base + DSDT_OFFSET); 317243327Sgrehan EFPRINTF(fp, "[0001]\t\tModel : 00\n"); 318243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM Profile : 00 [Unspecified]\n"); 319243327Sgrehan EFPRINTF(fp, "[0002]\t\tSCI Interrupt : 0009\n"); 320243327Sgrehan EFPRINTF(fp, "[0004]\t\tSMI Command Port : 00000000\n"); 321243327Sgrehan EFPRINTF(fp, "[0001]\t\tACPI Enable Value : 00\n"); 322243327Sgrehan EFPRINTF(fp, "[0001]\t\tACPI Disable Value : 00\n"); 323243327Sgrehan EFPRINTF(fp, "[0001]\t\tS4BIOS Command : 00\n"); 324243327Sgrehan EFPRINTF(fp, "[0001]\t\tP-State Control : 00\n"); 325243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM1A Event Block Address : 00000000\n"); 326243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM1B Event Block Address : 00000000\n"); 327243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM1A Control Block Address : 00000000\n"); 328243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM1B Control Block Address : 00000000\n"); 329243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM2 Control Block Address : 00000000\n"); 330243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM Timer Block Address : %08X\n", 331243327Sgrehan BHYVE_PM_TIMER_ADDR); 332243327Sgrehan EFPRINTF(fp, "[0004]\t\tGPE0 Block Address : 00000000\n"); 333243327Sgrehan EFPRINTF(fp, "[0004]\t\tGPE1 Block Address : 00000000\n"); 334243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM1 Event Block Length : 04\n"); 335243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM1 Control Block Length : 02\n"); 336243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM2 Control Block Length : 00\n"); 337243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM Timer Block Length : 04\n"); 338243327Sgrehan EFPRINTF(fp, "[0001]\t\tGPE0 Block Length : 00\n"); 339243327Sgrehan EFPRINTF(fp, "[0001]\t\tGPE1 Block Length : 00\n"); 340243327Sgrehan EFPRINTF(fp, "[0001]\t\tGPE1 Base Offset : 00\n"); 341243327Sgrehan EFPRINTF(fp, "[0001]\t\t_CST Support : 00\n"); 342243327Sgrehan EFPRINTF(fp, "[0002]\t\tC2 Latency : 0000\n"); 343243327Sgrehan EFPRINTF(fp, "[0002]\t\tC3 Latency : 0000\n"); 344243327Sgrehan EFPRINTF(fp, "[0002]\t\tCPU Cache Size : 0000\n"); 345243327Sgrehan EFPRINTF(fp, "[0002]\t\tCache Flush Stride : 0000\n"); 346243327Sgrehan EFPRINTF(fp, "[0001]\t\tDuty Cycle Offset : 00\n"); 347243327Sgrehan EFPRINTF(fp, "[0001]\t\tDuty Cycle Width : 00\n"); 348243327Sgrehan EFPRINTF(fp, "[0001]\t\tRTC Day Alarm Index : 00\n"); 349243327Sgrehan EFPRINTF(fp, "[0001]\t\tRTC Month Alarm Index : 00\n"); 350243327Sgrehan EFPRINTF(fp, "[0001]\t\tRTC Century Index : 00\n"); 351243327Sgrehan EFPRINTF(fp, "[0002]\t\tBoot Flags (decoded below) : 0000\n"); 352243327Sgrehan EFPRINTF(fp, "\t\t\tLegacy Devices Supported (V2) : 0\n"); 353243327Sgrehan EFPRINTF(fp, "\t\t\t8042 Present on ports 60/64 (V2) : 0\n"); 354243327Sgrehan EFPRINTF(fp, "\t\t\tVGA Not Present (V4) : 1\n"); 355243327Sgrehan EFPRINTF(fp, "\t\t\tMSI Not Supported (V4) : 0\n"); 356243327Sgrehan EFPRINTF(fp, "\t\t\tPCIe ASPM Not Supported (V4) : 1\n"); 357243327Sgrehan EFPRINTF(fp, "\t\t\tCMOS RTC Not Present (V5) : 0\n"); 358243327Sgrehan EFPRINTF(fp, "[0001]\t\tReserved : 00\n"); 359243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n"); 360243327Sgrehan EFPRINTF(fp, "\t\t\tWBINVD instruction is operational (V1) : 1\n"); 361243327Sgrehan EFPRINTF(fp, "\t\t\tWBINVD flushes all caches (V1) : 0\n"); 362243327Sgrehan EFPRINTF(fp, "\t\t\tAll CPUs support C1 (V1) : 0\n"); 363243327Sgrehan EFPRINTF(fp, "\t\t\tC2 works on MP system (V1) : 0\n"); 364243327Sgrehan EFPRINTF(fp, "\t\t\tControl Method Power Button (V1) : 1\n"); 365243327Sgrehan EFPRINTF(fp, "\t\t\tControl Method Sleep Button (V1) : 1\n"); 366243327Sgrehan EFPRINTF(fp, "\t\t\tRTC wake not in fixed reg space (V1) : 0\n"); 367243327Sgrehan EFPRINTF(fp, "\t\t\tRTC can wake system from S4 (V1) : 0\n"); 368243327Sgrehan EFPRINTF(fp, "\t\t\t32-bit PM Timer (V1) : 1\n"); 369243327Sgrehan EFPRINTF(fp, "\t\t\tDocking Supported (V1) : 0\n"); 370243327Sgrehan EFPRINTF(fp, "\t\t\tReset Register Supported (V2) : 0\n"); 371243327Sgrehan EFPRINTF(fp, "\t\t\tSealed Case (V3) : 0\n"); 372243327Sgrehan EFPRINTF(fp, "\t\t\tHeadless - No Video (V3) : 1\n"); 373243327Sgrehan EFPRINTF(fp, "\t\t\tUse native instr after SLP_TYPx (V3) : 0\n"); 374243327Sgrehan EFPRINTF(fp, "\t\t\tPCIEXP_WAK Bits Supported (V4) : 0\n"); 375243327Sgrehan EFPRINTF(fp, "\t\t\tUse Platform Timer (V4) : 0\n"); 376243327Sgrehan EFPRINTF(fp, "\t\t\tRTC_STS valid on S4 wake (V4) : 0\n"); 377243327Sgrehan EFPRINTF(fp, "\t\t\tRemote Power-on capable (V4) : 0\n"); 378243327Sgrehan EFPRINTF(fp, "\t\t\tUse APIC Cluster Model (V4) : 0\n"); 379243327Sgrehan EFPRINTF(fp, "\t\t\tUse APIC Physical Destination Mode (V4) : 1\n"); 380243327Sgrehan EFPRINTF(fp, "\t\t\tHardware Reduced (V5) : 0\n"); 381243327Sgrehan EFPRINTF(fp, "\t\t\tLow Power S0 Idle (V5) : 0\n"); 382243327Sgrehan EFPRINTF(fp, "\n"); 383243327Sgrehan 384243327Sgrehan EFPRINTF(fp, 385243327Sgrehan "[0012]\t\tReset Register : [Generic Address Structure]\n"); 386243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 387243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 388243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 389243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 390243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n"); 391243327Sgrehan EFPRINTF(fp, "\n"); 392243327Sgrehan 393243327Sgrehan EFPRINTF(fp, "[0001]\t\tValue to cause reset : 00\n"); 394243327Sgrehan EFPRINTF(fp, "[0003]\t\tReserved : 000000\n"); 395243327Sgrehan EFPRINTF(fp, "[0008]\t\tFACS Address : 00000000%08X\n", 396243327Sgrehan basl_acpi_base + FACS_OFFSET); 397243327Sgrehan EFPRINTF(fp, "[0008]\t\tDSDT Address : 00000000%08X\n", 398243327Sgrehan basl_acpi_base + DSDT_OFFSET); 399243327Sgrehan EFPRINTF(fp, 400243327Sgrehan "[0012]\t\tPM1A Event Block : [Generic Address Structure]\n"); 401243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 402243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 20\n"); 403243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 404243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n"); 405243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n"); 406243327Sgrehan EFPRINTF(fp, "\n"); 407243327Sgrehan 408243327Sgrehan EFPRINTF(fp, 409243327Sgrehan "[0012]\t\tPM1B Event Block : [Generic Address Structure]\n"); 410243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 411243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 412243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 413243327Sgrehan EFPRINTF(fp, 414243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 415243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 416243327Sgrehan EFPRINTF(fp, "\n"); 417243327Sgrehan 418243327Sgrehan EFPRINTF(fp, 419243327Sgrehan "[0012]\t\tPM1A Control Block : [Generic Address Structure]\n"); 420243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 421243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 10\n"); 422243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 423243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n"); 424243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n"); 425243327Sgrehan EFPRINTF(fp, "\n"); 426243327Sgrehan 427243327Sgrehan EFPRINTF(fp, 428243327Sgrehan "[0012]\t\tPM1B Control Block : [Generic Address Structure]\n"); 429243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 430243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 431243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 432243327Sgrehan EFPRINTF(fp, 433243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 434243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 435243327Sgrehan EFPRINTF(fp, "\n"); 436243327Sgrehan 437243327Sgrehan EFPRINTF(fp, 438243327Sgrehan "[0012]\t\tPM2 Control Block : [Generic Address Structure]\n"); 439243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 440243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 441243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 442243327Sgrehan EFPRINTF(fp, 443243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 444243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 445243327Sgrehan EFPRINTF(fp, "\n"); 446243327Sgrehan 447243327Sgrehan /* Valid for bhyve */ 448243327Sgrehan EFPRINTF(fp, 449243327Sgrehan "[0012]\t\tPM Timer Block : [Generic Address Structure]\n"); 450243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 451243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 32\n"); 452243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 453243327Sgrehan EFPRINTF(fp, 454243327Sgrehan "[0001]\t\tEncoded Access Width : 03 [DWord Access:32]\n"); 455243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n", 456243327Sgrehan BHYVE_PM_TIMER_ADDR); 457243327Sgrehan EFPRINTF(fp, "\n"); 458243327Sgrehan 459243327Sgrehan EFPRINTF(fp, "[0012]\t\tGPE0 Block : [Generic Address Structure]\n"); 460243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 461243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 80\n"); 462243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 463243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 464243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 465243327Sgrehan EFPRINTF(fp, "\n"); 466243327Sgrehan 467243327Sgrehan EFPRINTF(fp, "[0012]\t\tGPE1 Block : [Generic Address Structure]\n"); 468243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 469243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 470243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 471243327Sgrehan EFPRINTF(fp, 472243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 473243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 474243327Sgrehan EFPRINTF(fp, "\n"); 475243327Sgrehan 476243327Sgrehan EFPRINTF(fp, 477243327Sgrehan "[0012]\t\tSleep Control Register : [Generic Address Structure]\n"); 478243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 479243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 480243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 481243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 482243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 483243327Sgrehan EFPRINTF(fp, "\n"); 484243327Sgrehan 485243327Sgrehan EFPRINTF(fp, 486243327Sgrehan "[0012]\t\tSleep Status Register : [Generic Address Structure]\n"); 487243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 488243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 489243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 490243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 491243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 492243327Sgrehan 493243327Sgrehan EFFLUSH(fp); 494243327Sgrehan 495243327Sgrehan return (0); 496243327Sgrehan 497243327Sgrehanerr_exit: 498243327Sgrehan return (errno); 499243327Sgrehan} 500243327Sgrehan 501243327Sgrehanstatic int 502243327Sgrehanbasl_fwrite_facs(FILE *fp) 503243327Sgrehan{ 504243327Sgrehan int err; 505243327Sgrehan 506243327Sgrehan err = 0; 507243327Sgrehan 508243327Sgrehan EFPRINTF(fp, "/*\n"); 509243327Sgrehan EFPRINTF(fp, " * bhyve FACS template\n"); 510243327Sgrehan EFPRINTF(fp, " */\n"); 511243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"FACS\"\n"); 512243327Sgrehan EFPRINTF(fp, "[0004]\t\tLength : 00000040\n"); 513243327Sgrehan EFPRINTF(fp, "[0004]\t\tHardware Signature : 00000000\n"); 514243327Sgrehan EFPRINTF(fp, "[0004]\t\t32 Firmware Waking Vector : 00000000\n"); 515243327Sgrehan EFPRINTF(fp, "[0004]\t\tGlobal Lock : 00000000\n"); 516243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n"); 517243327Sgrehan EFPRINTF(fp, "\t\t\tS4BIOS Support Present : 0\n"); 518243327Sgrehan EFPRINTF(fp, "\t\t\t64-bit Wake Supported (V2) : 0\n"); 519243327Sgrehan EFPRINTF(fp, 520243327Sgrehan "[0008]\t\t64 Firmware Waking Vector : 0000000000000000\n"); 521243327Sgrehan EFPRINTF(fp, "[0001]\t\tVersion : 02\n"); 522243327Sgrehan EFPRINTF(fp, "[0003]\t\tReserved : 000000\n"); 523243327Sgrehan EFPRINTF(fp, "[0004]\t\tOspmFlags (decoded below) : 00000000\n"); 524243327Sgrehan EFPRINTF(fp, "\t\t\t64-bit Wake Env Required (V2) : 0\n"); 525243327Sgrehan 526243327Sgrehan EFFLUSH(fp); 527243327Sgrehan 528243327Sgrehan return (0); 529243327Sgrehan 530243327Sgrehanerr_exit: 531243327Sgrehan return (errno); 532243327Sgrehan} 533243327Sgrehan 534243327Sgrehanstatic int 535243327Sgrehanbasl_fwrite_dsdt(FILE *fp) 536243327Sgrehan{ 537243327Sgrehan int err; 538243327Sgrehan 539243327Sgrehan err = 0; 540243327Sgrehan 541243327Sgrehan EFPRINTF(fp, "/*\n"); 542243327Sgrehan EFPRINTF(fp, " * bhyve DSDT template\n"); 543243327Sgrehan EFPRINTF(fp, " */\n"); 544243327Sgrehan EFPRINTF(fp, "DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2," 545243704Sgrehan "\"BHYVE \", \"BVDSDT \", 0x00000001)\n"); 546243327Sgrehan EFPRINTF(fp, "{\n"); 547243327Sgrehan EFPRINTF(fp, " Scope (_SB)\n"); 548243327Sgrehan EFPRINTF(fp, " {\n"); 549243327Sgrehan EFPRINTF(fp, " Device (PCI0)\n"); 550243327Sgrehan EFPRINTF(fp, " {\n"); 551243327Sgrehan EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0A03\"))\n"); 552243327Sgrehan EFPRINTF(fp, " Name (_ADR, Zero)\n"); 553243327Sgrehan EFPRINTF(fp, " Name (_UID, One)\n"); 554243327Sgrehan EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n"); 555243327Sgrehan EFPRINTF(fp, " {\n"); 556243327Sgrehan EFPRINTF(fp, " WordBusNumber (ResourceProducer, MinFixed," 557243327Sgrehan "MaxFixed, PosDecode,\n"); 558243327Sgrehan EFPRINTF(fp, " 0x0000, // Granularity\n"); 559243327Sgrehan EFPRINTF(fp, " 0x0000, // Range Minimum\n"); 560243327Sgrehan EFPRINTF(fp, " 0x00FF, // Range Maximum\n"); 561243327Sgrehan EFPRINTF(fp, " 0x0000, // Transl Offset\n"); 562243327Sgrehan EFPRINTF(fp, " 0x0100, // Length\n"); 563243327Sgrehan EFPRINTF(fp, " ,, )\n"); 564243327Sgrehan EFPRINTF(fp, " IO (Decode16,\n"); 565243327Sgrehan EFPRINTF(fp, " 0x0CF8, // Range Minimum\n"); 566243327Sgrehan EFPRINTF(fp, " 0x0CF8, // Range Maximum\n"); 567243327Sgrehan EFPRINTF(fp, " 0x01, // Alignment\n"); 568243327Sgrehan EFPRINTF(fp, " 0x08, // Length\n"); 569243327Sgrehan EFPRINTF(fp, " )\n"); 570243327Sgrehan EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed," 571243327Sgrehan "PosDecode, EntireRange,\n"); 572243327Sgrehan EFPRINTF(fp, " 0x0000, // Granularity\n"); 573243327Sgrehan EFPRINTF(fp, " 0x0000, // Range Minimum\n"); 574243327Sgrehan EFPRINTF(fp, " 0x0CF7, // Range Maximum\n"); 575243327Sgrehan EFPRINTF(fp, " 0x0000, // Transl Offset\n"); 576243327Sgrehan EFPRINTF(fp, " 0x0CF8, // Length\n"); 577243327Sgrehan EFPRINTF(fp, " ,, , TypeStatic)\n"); 578243327Sgrehan EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed," 579243327Sgrehan "PosDecode, EntireRange,\n"); 580243327Sgrehan EFPRINTF(fp, " 0x0000, // Granularity\n"); 581243327Sgrehan EFPRINTF(fp, " 0x0D00, // Range Minimum\n"); 582243327Sgrehan EFPRINTF(fp, " 0xFFFF, // Range Maximum\n"); 583243327Sgrehan EFPRINTF(fp, " 0x0000, // Transl Offset\n"); 584243327Sgrehan EFPRINTF(fp, " 0xF300, // Length\n"); 585243327Sgrehan EFPRINTF(fp, " ,, , TypeStatic)\n"); 586243327Sgrehan EFPRINTF(fp, " })\n"); 587243327Sgrehan EFPRINTF(fp, " }\n"); 588243327Sgrehan EFPRINTF(fp, " }\n"); 589243327Sgrehan EFPRINTF(fp, "\n"); 590243327Sgrehan EFPRINTF(fp, " Scope (_SB.PCI0)\n"); 591243327Sgrehan EFPRINTF(fp, " {\n"); 592243327Sgrehan EFPRINTF(fp, " Device (ISA)\n"); 593243327Sgrehan EFPRINTF(fp, " {\n"); 594243327Sgrehan EFPRINTF(fp, " Name (_ADR, 0x00010000)\n"); 595243327Sgrehan EFPRINTF(fp, " OperationRegion (P40C, PCI_Config, 0x60, 0x04)\n"); 596243327Sgrehan EFPRINTF(fp, " }\n"); 597243327Sgrehan EFPRINTF(fp, " }\n"); 598243327Sgrehan EFPRINTF(fp, "\n"); 599243327Sgrehan EFPRINTF(fp, " Scope (_SB.PCI0.ISA)\n"); 600243327Sgrehan EFPRINTF(fp, " {\n"); 601243327Sgrehan EFPRINTF(fp, " Device (RTC)\n"); 602243327Sgrehan EFPRINTF(fp, " {\n"); 603243327Sgrehan EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0B00\"))\n"); 604243327Sgrehan EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n"); 605243327Sgrehan EFPRINTF(fp, " {\n"); 606243327Sgrehan EFPRINTF(fp, " IO (Decode16,\n"); 607243327Sgrehan EFPRINTF(fp, " 0x0070, // Range Minimum\n"); 608243327Sgrehan EFPRINTF(fp, " 0x0070, // Range Maximum\n"); 609243327Sgrehan EFPRINTF(fp, " 0x10, // Alignment\n"); 610243327Sgrehan EFPRINTF(fp, " 0x02, // Length\n"); 611243327Sgrehan EFPRINTF(fp, " )\n"); 612243327Sgrehan EFPRINTF(fp, " IRQNoFlags ()\n"); 613243327Sgrehan EFPRINTF(fp, " {8}\n"); 614243327Sgrehan EFPRINTF(fp, " IO (Decode16,\n"); 615243327Sgrehan EFPRINTF(fp, " 0x0072, // Range Minimum\n"); 616243327Sgrehan EFPRINTF(fp, " 0x0072, // Range Maximum\n"); 617243327Sgrehan EFPRINTF(fp, " 0x02, // Alignment\n"); 618243327Sgrehan EFPRINTF(fp, " 0x06, // Length\n"); 619243327Sgrehan EFPRINTF(fp, " )\n"); 620243327Sgrehan EFPRINTF(fp, " })\n"); 621243327Sgrehan EFPRINTF(fp, " }\n"); 622243327Sgrehan EFPRINTF(fp, " }\n"); 623243327Sgrehan EFPRINTF(fp, "}\n"); 624243327Sgrehan 625243327Sgrehan EFFLUSH(fp); 626243327Sgrehan 627243327Sgrehan return (0); 628243327Sgrehan 629243327Sgrehanerr_exit: 630243327Sgrehan return (errno); 631243327Sgrehan} 632243327Sgrehan 633243327Sgrehanstatic int 634243327Sgrehanbasl_open(struct basl_fio *bf, int suffix) 635243327Sgrehan{ 636243327Sgrehan int err; 637243327Sgrehan 638243327Sgrehan err = 0; 639243327Sgrehan 640243327Sgrehan if (suffix) { 641243327Sgrehan strncpy(bf->f_name, basl_stemplate, MAXPATHLEN); 642243327Sgrehan bf->fd = mkstemps(bf->f_name, strlen(BHYVE_ASL_SUFFIX)); 643243327Sgrehan } else { 644243327Sgrehan strncpy(bf->f_name, basl_template, MAXPATHLEN); 645243327Sgrehan bf->fd = mkstemp(bf->f_name); 646243327Sgrehan } 647243327Sgrehan 648243327Sgrehan if (bf->fd > 0) { 649243327Sgrehan bf->fp = fdopen(bf->fd, "w+"); 650243327Sgrehan if (bf->fp == NULL) { 651243327Sgrehan unlink(bf->f_name); 652243327Sgrehan close(bf->fd); 653243327Sgrehan } 654243327Sgrehan } else { 655243327Sgrehan err = 1; 656243327Sgrehan } 657243327Sgrehan 658243327Sgrehan return (err); 659243327Sgrehan} 660243327Sgrehan 661243327Sgrehanstatic void 662243327Sgrehanbasl_close(struct basl_fio *bf) 663243327Sgrehan{ 664243327Sgrehan 665243327Sgrehan if (!basl_keep_temps) 666243327Sgrehan unlink(bf->f_name); 667243327Sgrehan fclose(bf->fp); 668243327Sgrehan} 669243327Sgrehan 670243327Sgrehanstatic int 671243327Sgrehanbasl_start(struct basl_fio *in, struct basl_fio *out) 672243327Sgrehan{ 673243327Sgrehan int err; 674243327Sgrehan 675243327Sgrehan err = basl_open(in, 0); 676243327Sgrehan if (!err) { 677243327Sgrehan err = basl_open(out, 1); 678243327Sgrehan if (err) { 679243327Sgrehan basl_close(in); 680243327Sgrehan } 681243327Sgrehan } 682243327Sgrehan 683243327Sgrehan return (err); 684243327Sgrehan} 685243327Sgrehan 686243327Sgrehanstatic void 687243327Sgrehanbasl_end(struct basl_fio *in, struct basl_fio *out) 688243327Sgrehan{ 689243327Sgrehan 690243327Sgrehan basl_close(in); 691243327Sgrehan basl_close(out); 692243327Sgrehan} 693243327Sgrehan 694243327Sgrehanstatic int 695248477Sneelbasl_load(struct vmctx *ctx, int fd, uint64_t off) 696243327Sgrehan{ 697248477Sneel struct stat sb; 698247523Sneel void *gaddr; 699243327Sgrehan 700248477Sneel if (fstat(fd, &sb) < 0) 701248477Sneel return (errno); 702248477Sneel 703248477Sneel gaddr = paddr_guest2host(ctx, basl_acpi_base + off, sb.st_size); 704248477Sneel if (gaddr == NULL) 705248477Sneel return (EFAULT); 706243327Sgrehan 707248477Sneel if (read(fd, gaddr, sb.st_size) < 0) 708248477Sneel return (errno); 709248477Sneel 710248477Sneel return (0); 711243327Sgrehan} 712243327Sgrehan 713243327Sgrehanstatic int 714248477Sneelbasl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *), uint64_t offset) 715243327Sgrehan{ 716243327Sgrehan struct basl_fio io[2]; 717243327Sgrehan static char iaslbuf[3*MAXPATHLEN + 10]; 718243327Sgrehan char *fmt; 719243327Sgrehan int err; 720243327Sgrehan 721243327Sgrehan err = basl_start(&io[0], &io[1]); 722243327Sgrehan if (!err) { 723243327Sgrehan err = (*fwrite_section)(io[0].fp); 724243327Sgrehan 725243327Sgrehan if (!err) { 726243327Sgrehan /* 727243327Sgrehan * iasl sends the results of the compilation to 728243327Sgrehan * stdout. Shut this down by using the shell to 729243327Sgrehan * redirect stdout to /dev/null, unless the user 730243327Sgrehan * has requested verbose output for debugging 731243327Sgrehan * purposes 732243327Sgrehan */ 733243327Sgrehan fmt = basl_verbose_iasl ? 734243327Sgrehan "%s -p %s %s" : 735243327Sgrehan "/bin/sh -c \"%s -p %s %s\" 1> /dev/null"; 736243327Sgrehan 737243327Sgrehan snprintf(iaslbuf, sizeof(iaslbuf), 738243327Sgrehan fmt, 739243327Sgrehan BHYVE_ASL_COMPILER, 740243327Sgrehan io[1].f_name, io[0].f_name); 741243327Sgrehan err = system(iaslbuf); 742243327Sgrehan 743243327Sgrehan if (!err) { 744243327Sgrehan /* 745243327Sgrehan * Copy the aml output file into guest 746243327Sgrehan * memory at the specified location 747243327Sgrehan */ 748248477Sneel err = basl_load(ctx, io[1].fd, offset); 749243327Sgrehan } 750243327Sgrehan } 751243327Sgrehan basl_end(&io[0], &io[1]); 752243327Sgrehan } 753243327Sgrehan 754243327Sgrehan return (err); 755243327Sgrehan} 756243327Sgrehan 757243327Sgrehanstatic int 758243327Sgrehanbasl_make_templates(void) 759243327Sgrehan{ 760243327Sgrehan const char *tmpdir; 761243327Sgrehan int err; 762243327Sgrehan int len; 763243327Sgrehan 764243327Sgrehan err = 0; 765243327Sgrehan 766243327Sgrehan /* 767243327Sgrehan * 768243327Sgrehan */ 769243327Sgrehan if ((tmpdir = getenv("BHYVE_TMPDIR")) == NULL || *tmpdir == '\0' || 770243327Sgrehan (tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') { 771243327Sgrehan tmpdir = _PATH_TMP; 772243327Sgrehan } 773243327Sgrehan 774243327Sgrehan len = strlen(tmpdir); 775243327Sgrehan 776243327Sgrehan if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1) < MAXPATHLEN) { 777243327Sgrehan strcpy(basl_template, tmpdir); 778243327Sgrehan while (len > 0 && basl_template[len - 1] == '/') 779243327Sgrehan len--; 780243327Sgrehan basl_template[len] = '/'; 781243327Sgrehan strcpy(&basl_template[len + 1], BHYVE_ASL_TEMPLATE); 782243327Sgrehan } else 783243327Sgrehan err = E2BIG; 784243327Sgrehan 785243327Sgrehan if (!err) { 786243327Sgrehan /* 787243327Sgrehan * len has been intialized (and maybe adjusted) above 788243327Sgrehan */ 789243327Sgrehan if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1 + 790243327Sgrehan sizeof(BHYVE_ASL_SUFFIX)) < MAXPATHLEN) { 791243327Sgrehan strcpy(basl_stemplate, tmpdir); 792243327Sgrehan basl_stemplate[len] = '/'; 793243327Sgrehan strcpy(&basl_stemplate[len + 1], BHYVE_ASL_TEMPLATE); 794243327Sgrehan len = strlen(basl_stemplate); 795243327Sgrehan strcpy(&basl_stemplate[len], BHYVE_ASL_SUFFIX); 796243327Sgrehan } else 797243327Sgrehan err = E2BIG; 798243327Sgrehan } 799243327Sgrehan 800243327Sgrehan return (err); 801243327Sgrehan} 802243327Sgrehan 803243327Sgrehanstatic struct { 804243327Sgrehan int (*wsect)(FILE *fp); 805243327Sgrehan uint64_t offset; 806243327Sgrehan} basl_ftables[] = 807243327Sgrehan{ 808243327Sgrehan { basl_fwrite_rsdp, 0}, 809243327Sgrehan { basl_fwrite_rsdt, RSDT_OFFSET }, 810243704Sgrehan { basl_fwrite_xsdt, XSDT_OFFSET }, 811243327Sgrehan { basl_fwrite_madt, MADT_OFFSET }, 812243327Sgrehan { basl_fwrite_fadt, FADT_OFFSET }, 813243327Sgrehan { basl_fwrite_facs, FACS_OFFSET }, 814243327Sgrehan { basl_fwrite_dsdt, DSDT_OFFSET }, 815243327Sgrehan { NULL } 816243327Sgrehan}; 817243327Sgrehan 818243327Sgrehanint 819259496Sgrehanacpi_build(struct vmctx *ctx, int ncpu) 820243327Sgrehan{ 821243327Sgrehan int err; 822243327Sgrehan int i; 823243327Sgrehan 824243327Sgrehan err = 0; 825243327Sgrehan basl_ncpu = ncpu; 826243327Sgrehan 827243327Sgrehan /* 828243327Sgrehan * For debug, allow the user to have iasl compiler output sent 829243327Sgrehan * to stdout rather than /dev/null 830243327Sgrehan */ 831243327Sgrehan if (getenv("BHYVE_ACPI_VERBOSE_IASL")) 832243327Sgrehan basl_verbose_iasl = 1; 833243327Sgrehan 834243327Sgrehan /* 835243327Sgrehan * Allow the user to keep the generated ASL files for debugging 836243327Sgrehan * instead of deleting them following use 837243327Sgrehan */ 838243327Sgrehan if (getenv("BHYVE_ACPI_KEEPTMPS")) 839243327Sgrehan basl_keep_temps = 1; 840243327Sgrehan 841243327Sgrehan i = 0; 842243327Sgrehan err = basl_make_templates(); 843243327Sgrehan 844243327Sgrehan /* 845243327Sgrehan * Run through all the ASL files, compiling them and 846243327Sgrehan * copying them into guest memory 847243327Sgrehan */ 848243327Sgrehan while (!err && basl_ftables[i].wsect != NULL) { 849248477Sneel err = basl_compile(ctx, basl_ftables[i].wsect, 850243327Sgrehan basl_ftables[i].offset); 851243327Sgrehan i++; 852243327Sgrehan } 853243327Sgrehan 854243327Sgrehan return (err); 855243327Sgrehan} 856