qemu/hw/acpi/aml-build.c
<<
>>
Prefs
   1/* Support for generating ACPI tables and passing them to Guests
   2 *
   3 * Copyright (C) 2015 Red Hat Inc
   4 *
   5 * Author: Michael S. Tsirkin <mst@redhat.com>
   6 * Author: Igor Mammedov <imammedo@redhat.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17
  18 * You should have received a copy of the GNU General Public License along
  19 * with this program; if not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include "qemu/osdep.h"
  23#include <glib/gprintf.h>
  24#include "hw/acpi/aml-build.h"
  25#include "qemu/bswap.h"
  26#include "qemu/bitops.h"
  27#include "sysemu/numa.h"
  28#include "hw/boards.h"
  29
  30static GArray *build_alloc_array(void)
  31{
  32    return g_array_new(false, true /* clear */, 1);
  33}
  34
  35static void build_free_array(GArray *array)
  36{
  37    g_array_free(array, true);
  38}
  39
  40static void build_prepend_byte(GArray *array, uint8_t val)
  41{
  42    g_array_prepend_val(array, val);
  43}
  44
  45static void build_append_byte(GArray *array, uint8_t val)
  46{
  47    g_array_append_val(array, val);
  48}
  49
  50static void build_append_array(GArray *array, GArray *val)
  51{
  52    g_array_append_vals(array, val->data, val->len);
  53}
  54
  55#define ACPI_NAMESEG_LEN 4
  56
  57static void
  58build_append_nameseg(GArray *array, const char *seg)
  59{
  60    int len;
  61
  62    len = strlen(seg);
  63    assert(len <= ACPI_NAMESEG_LEN);
  64
  65    g_array_append_vals(array, seg, len);
  66    /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */
  67    g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len);
  68}
  69
  70static void GCC_FMT_ATTR(2, 0)
  71build_append_namestringv(GArray *array, const char *format, va_list ap)
  72{
  73    char *s;
  74    char **segs;
  75    char **segs_iter;
  76    int seg_count = 0;
  77
  78    s = g_strdup_vprintf(format, ap);
  79    segs = g_strsplit(s, ".", 0);
  80    g_free(s);
  81
  82    /* count segments */
  83    segs_iter = segs;
  84    while (*segs_iter) {
  85        ++segs_iter;
  86        ++seg_count;
  87    }
  88    /*
  89     * ACPI 5.0 spec: 20.2.2 Name Objects Encoding:
  90     * "SegCount can be from 1 to 255"
  91     */
  92    assert(seg_count > 0 && seg_count <= 255);
  93
  94    /* handle RootPath || PrefixPath */
  95    s = *segs;
  96    while (*s == '\\' || *s == '^') {
  97        build_append_byte(array, *s);
  98        ++s;
  99    }
 100
 101    switch (seg_count) {
 102    case 1:
 103        if (!*s) {
 104            build_append_byte(array, 0x00); /* NullName */
 105        } else {
 106            build_append_nameseg(array, s);
 107        }
 108        break;
 109
 110    case 2:
 111        build_append_byte(array, 0x2E); /* DualNamePrefix */
 112        build_append_nameseg(array, s);
 113        build_append_nameseg(array, segs[1]);
 114        break;
 115    default:
 116        build_append_byte(array, 0x2F); /* MultiNamePrefix */
 117        build_append_byte(array, seg_count);
 118
 119        /* handle the 1st segment manually due to prefix/root path */
 120        build_append_nameseg(array, s);
 121
 122        /* add the rest of segments */
 123        segs_iter = segs + 1;
 124        while (*segs_iter) {
 125            build_append_nameseg(array, *segs_iter);
 126            ++segs_iter;
 127        }
 128        break;
 129    }
 130    g_strfreev(segs);
 131}
 132
 133GCC_FMT_ATTR(2, 3)
 134static void build_append_namestring(GArray *array, const char *format, ...)
 135{
 136    va_list ap;
 137
 138    va_start(ap, format);
 139    build_append_namestringv(array, format, ap);
 140    va_end(ap);
 141}
 142
 143/* 5.4 Definition Block Encoding */
 144enum {
 145    PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
 146    PACKAGE_LENGTH_2BYTE_SHIFT = 4,
 147    PACKAGE_LENGTH_3BYTE_SHIFT = 12,
 148    PACKAGE_LENGTH_4BYTE_SHIFT = 20,
 149};
 150
 151static void
 152build_prepend_package_length(GArray *package, unsigned length, bool incl_self)
 153{
 154    uint8_t byte;
 155    unsigned length_bytes;
 156
 157    if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
 158        length_bytes = 1;
 159    } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
 160        length_bytes = 2;
 161    } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
 162        length_bytes = 3;
 163    } else {
 164        length_bytes = 4;
 165    }
 166
 167    /*
 168     * NamedField uses PkgLength encoding but it doesn't include length
 169     * of PkgLength itself.
 170     */
 171    if (incl_self) {
 172        /*
 173         * PkgLength is the length of the inclusive length of the data
 174         * and PkgLength's length itself when used for terms with
 175         * explitit length.
 176         */
 177        length += length_bytes;
 178    }
 179
 180    switch (length_bytes) {
 181    case 1:
 182        byte = length;
 183        build_prepend_byte(package, byte);
 184        return;
 185    case 4:
 186        byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
 187        build_prepend_byte(package, byte);
 188        length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
 189        /* fall through */
 190    case 3:
 191        byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
 192        build_prepend_byte(package, byte);
 193        length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
 194        /* fall through */
 195    case 2:
 196        byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
 197        build_prepend_byte(package, byte);
 198        length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
 199        /* fall through */
 200    }
 201    /*
 202     * Most significant two bits of byte zero indicate how many following bytes
 203     * are in PkgLength encoding.
 204     */
 205    byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
 206    build_prepend_byte(package, byte);
 207}
 208
 209static void
 210build_append_pkg_length(GArray *array, unsigned length, bool incl_self)
 211{
 212    GArray *tmp = build_alloc_array();
 213
 214    build_prepend_package_length(tmp, length, incl_self);
 215    build_append_array(array, tmp);
 216    build_free_array(tmp);
 217}
 218
 219static void build_package(GArray *package, uint8_t op)
 220{
 221    build_prepend_package_length(package, package->len, true);
 222    build_prepend_byte(package, op);
 223}
 224
 225static void build_extop_package(GArray *package, uint8_t op)
 226{
 227    build_package(package, op);
 228    build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
 229}
 230
 231void build_append_int_noprefix(GArray *table, uint64_t value, int size)
 232{
 233    int i;
 234
 235    for (i = 0; i < size; ++i) {
 236        build_append_byte(table, value & 0xFF);
 237        value = value >> 8;
 238    }
 239}
 240
 241static void build_append_int(GArray *table, uint64_t value)
 242{
 243    if (value == 0x00) {
 244        build_append_byte(table, 0x00); /* ZeroOp */
 245    } else if (value == 0x01) {
 246        build_append_byte(table, 0x01); /* OneOp */
 247    } else if (value <= 0xFF) {
 248        build_append_byte(table, 0x0A); /* BytePrefix */
 249        build_append_int_noprefix(table, value, 1);
 250    } else if (value <= 0xFFFF) {
 251        build_append_byte(table, 0x0B); /* WordPrefix */
 252        build_append_int_noprefix(table, value, 2);
 253    } else if (value <= 0xFFFFFFFF) {
 254        build_append_byte(table, 0x0C); /* DWordPrefix */
 255        build_append_int_noprefix(table, value, 4);
 256    } else {
 257        build_append_byte(table, 0x0E); /* QWordPrefix */
 258        build_append_int_noprefix(table, value, 8);
 259    }
 260}
 261
 262/* Generic Address Structure (GAS)
 263 * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
 264 * 2.0 compat note:
 265 *    @access_width must be 0, see ACPI 2.0:Table 5-1
 266 */
 267void build_append_gas(GArray *table, AmlAddressSpace as,
 268                      uint8_t bit_width, uint8_t bit_offset,
 269                      uint8_t access_width, uint64_t address)
 270{
 271    build_append_int_noprefix(table, as, 1);
 272    build_append_int_noprefix(table, bit_width, 1);
 273    build_append_int_noprefix(table, bit_offset, 1);
 274    build_append_int_noprefix(table, access_width, 1);
 275    build_append_int_noprefix(table, address, 8);
 276}
 277
 278/*
 279 * Build NAME(XXXX, 0x00000000) where 0x00000000 is encoded as a dword,
 280 * and return the offset to 0x00000000 for runtime patching.
 281 *
 282 * Warning: runtime patching is best avoided. Only use this as
 283 * a replacement for DataTableRegion (for guests that don't
 284 * support it).
 285 */
 286int
 287build_append_named_dword(GArray *array, const char *name_format, ...)
 288{
 289    int offset;
 290    va_list ap;
 291
 292    build_append_byte(array, 0x08); /* NameOp */
 293    va_start(ap, name_format);
 294    build_append_namestringv(array, name_format, ap);
 295    va_end(ap);
 296
 297    build_append_byte(array, 0x0C); /* DWordPrefix */
 298
 299    offset = array->len;
 300    build_append_int_noprefix(array, 0x00000000, 4);
 301    assert(array->len == offset + 4);
 302
 303    return offset;
 304}
 305
 306static GPtrArray *alloc_list;
 307
 308static Aml *aml_alloc(void)
 309{
 310    Aml *var = g_new0(typeof(*var), 1);
 311
 312    g_ptr_array_add(alloc_list, var);
 313    var->block_flags = AML_NO_OPCODE;
 314    var->buf = build_alloc_array();
 315    return var;
 316}
 317
 318static Aml *aml_opcode(uint8_t op)
 319{
 320    Aml *var = aml_alloc();
 321
 322    var->op  = op;
 323    var->block_flags = AML_OPCODE;
 324    return var;
 325}
 326
 327static Aml *aml_bundle(uint8_t op, AmlBlockFlags flags)
 328{
 329    Aml *var = aml_alloc();
 330
 331    var->op  = op;
 332    var->block_flags = flags;
 333    return var;
 334}
 335
 336static void aml_free(gpointer data, gpointer user_data)
 337{
 338    Aml *var = data;
 339    build_free_array(var->buf);
 340    g_free(var);
 341}
 342
 343Aml *init_aml_allocator(void)
 344{
 345    assert(!alloc_list);
 346    alloc_list = g_ptr_array_new();
 347    return aml_alloc();
 348}
 349
 350void free_aml_allocator(void)
 351{
 352    g_ptr_array_foreach(alloc_list, aml_free, NULL);
 353    g_ptr_array_free(alloc_list, true);
 354    alloc_list = 0;
 355}
 356
 357/* pack data with DefBuffer encoding */
 358static void build_buffer(GArray *array, uint8_t op)
 359{
 360    GArray *data = build_alloc_array();
 361
 362    build_append_int(data, array->len);
 363    g_array_prepend_vals(array, data->data, data->len);
 364    build_free_array(data);
 365    build_package(array, op);
 366}
 367
 368void aml_append(Aml *parent_ctx, Aml *child)
 369{
 370    GArray *buf = build_alloc_array();
 371    build_append_array(buf, child->buf);
 372
 373    switch (child->block_flags) {
 374    case AML_OPCODE:
 375        build_append_byte(parent_ctx->buf, child->op);
 376        break;
 377    case AML_EXT_PACKAGE:
 378        build_extop_package(buf, child->op);
 379        break;
 380    case AML_PACKAGE:
 381        build_package(buf, child->op);
 382        break;
 383    case AML_RES_TEMPLATE:
 384        build_append_byte(buf, 0x79); /* EndTag */
 385        /*
 386         * checksum operations are treated as succeeded if checksum
 387         * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag]
 388         */
 389        build_append_byte(buf, 0);
 390        /* fall through, to pack resources in buffer */
 391    case AML_BUFFER:
 392        build_buffer(buf, child->op);
 393        break;
 394    case AML_NO_OPCODE:
 395        break;
 396    default:
 397        assert(0);
 398        break;
 399    }
 400    build_append_array(parent_ctx->buf, buf);
 401    build_free_array(buf);
 402}
 403
 404/* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefScope */
 405Aml *aml_scope(const char *name_format, ...)
 406{
 407    va_list ap;
 408    Aml *var = aml_bundle(0x10 /* ScopeOp */, AML_PACKAGE);
 409    va_start(ap, name_format);
 410    build_append_namestringv(var->buf, name_format, ap);
 411    va_end(ap);
 412    return var;
 413}
 414
 415/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */
 416Aml *aml_return(Aml *val)
 417{
 418    Aml *var = aml_opcode(0xA4 /* ReturnOp */);
 419    aml_append(var, val);
 420    return var;
 421}
 422
 423/* ACPI 1.0b: 16.2.6.3 Debug Objects Encoding: DebugObj */
 424Aml *aml_debug(void)
 425{
 426    Aml *var = aml_alloc();
 427    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
 428    build_append_byte(var->buf, 0x31); /* DebugOp */
 429    return var;
 430}
 431
 432/*
 433 * ACPI 1.0b: 16.2.3 Data Objects Encoding:
 434 * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
 435 */
 436Aml *aml_int(const uint64_t val)
 437{
 438    Aml *var = aml_alloc();
 439    build_append_int(var->buf, val);
 440    return var;
 441}
 442
 443/*
 444 * helper to construct NameString, which returns Aml object
 445 * for using with aml_append or other aml_* terms
 446 */
 447Aml *aml_name(const char *name_format, ...)
 448{
 449    va_list ap;
 450    Aml *var = aml_alloc();
 451    va_start(ap, name_format);
 452    build_append_namestringv(var->buf, name_format, ap);
 453    va_end(ap);
 454    return var;
 455}
 456
 457/* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */
 458Aml *aml_name_decl(const char *name, Aml *val)
 459{
 460    Aml *var = aml_opcode(0x08 /* NameOp */);
 461    build_append_namestring(var->buf, "%s", name);
 462    aml_append(var, val);
 463    return var;
 464}
 465
 466/* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */
 467Aml *aml_arg(int pos)
 468{
 469    uint8_t op = 0x68 /* ARG0 op */ + pos;
 470
 471    assert(pos <= 6);
 472    return aml_opcode(op);
 473}
 474
 475/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToInteger */
 476Aml *aml_to_integer(Aml *arg)
 477{
 478    Aml *var = aml_opcode(0x99 /* ToIntegerOp */);
 479    aml_append(var, arg);
 480    build_append_byte(var->buf, 0x00 /* NullNameOp */);
 481    return var;
 482}
 483
 484/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToHexString */
 485Aml *aml_to_hexstring(Aml *src, Aml *dst)
 486{
 487    Aml *var = aml_opcode(0x98 /* ToHexStringOp */);
 488    aml_append(var, src);
 489    if (dst) {
 490        aml_append(var, dst);
 491    } else {
 492        build_append_byte(var->buf, 0x00 /* NullNameOp */);
 493    }
 494    return var;
 495}
 496
 497/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToBuffer */
 498Aml *aml_to_buffer(Aml *src, Aml *dst)
 499{
 500    Aml *var = aml_opcode(0x96 /* ToBufferOp */);
 501    aml_append(var, src);
 502    if (dst) {
 503        aml_append(var, dst);
 504    } else {
 505        build_append_byte(var->buf, 0x00 /* NullNameOp */);
 506    }
 507    return var;
 508}
 509
 510/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */
 511Aml *aml_store(Aml *val, Aml *target)
 512{
 513    Aml *var = aml_opcode(0x70 /* StoreOp */);
 514    aml_append(var, val);
 515    aml_append(var, target);
 516    return var;
 517}
 518
 519/**
 520 * build_opcode_2arg_dst:
 521 * @op: 1-byte opcode
 522 * @arg1: 1st operand
 523 * @arg2: 2nd operand
 524 * @dst: optional target to store to, set to NULL if it's not required
 525 *
 526 * An internal helper to compose AML terms that have
 527 *   "Op Operand Operand Target"
 528 * pattern.
 529 *
 530 * Returns: The newly allocated and composed according to patter Aml object.
 531 */
 532static Aml *
 533build_opcode_2arg_dst(uint8_t op, Aml *arg1, Aml *arg2, Aml *dst)
 534{
 535    Aml *var = aml_opcode(op);
 536    aml_append(var, arg1);
 537    aml_append(var, arg2);
 538    if (dst) {
 539        aml_append(var, dst);
 540    } else {
 541        build_append_byte(var->buf, 0x00 /* NullNameOp */);
 542    }
 543    return var;
 544}
 545
 546/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */
 547Aml *aml_and(Aml *arg1, Aml *arg2, Aml *dst)
 548{
 549    return build_opcode_2arg_dst(0x7B /* AndOp */, arg1, arg2, dst);
 550}
 551
 552/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefOr */
 553Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst)
 554{
 555    return build_opcode_2arg_dst(0x7D /* OrOp */, arg1, arg2, dst);
 556}
 557
 558/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLOr */
 559Aml *aml_lor(Aml *arg1, Aml *arg2)
 560{
 561    Aml *var = aml_opcode(0x91 /* LOrOp */);
 562    aml_append(var, arg1);
 563    aml_append(var, arg2);
 564    return var;
 565}
 566
 567/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftLeft */
 568Aml *aml_shiftleft(Aml *arg1, Aml *count)
 569{
 570    return build_opcode_2arg_dst(0x79 /* ShiftLeftOp */, arg1, count, NULL);
 571}
 572
 573/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftRight */
 574Aml *aml_shiftright(Aml *arg1, Aml *count, Aml *dst)
 575{
 576    return build_opcode_2arg_dst(0x7A /* ShiftRightOp */, arg1, count, dst);
 577}
 578
 579/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLLess */
 580Aml *aml_lless(Aml *arg1, Aml *arg2)
 581{
 582    Aml *var = aml_opcode(0x95 /* LLessOp */);
 583    aml_append(var, arg1);
 584    aml_append(var, arg2);
 585    return var;
 586}
 587
 588/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAdd */
 589Aml *aml_add(Aml *arg1, Aml *arg2, Aml *dst)
 590{
 591    return build_opcode_2arg_dst(0x72 /* AddOp */, arg1, arg2, dst);
 592}
 593
 594/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefSubtract */
 595Aml *aml_subtract(Aml *arg1, Aml *arg2, Aml *dst)
 596{
 597    return build_opcode_2arg_dst(0x74 /* SubtractOp */, arg1, arg2, dst);
 598}
 599
 600/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIncrement */
 601Aml *aml_increment(Aml *arg)
 602{
 603    Aml *var = aml_opcode(0x75 /* IncrementOp */);
 604    aml_append(var, arg);
 605    return var;
 606}
 607
 608/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDecrement */
 609Aml *aml_decrement(Aml *arg)
 610{
 611    Aml *var = aml_opcode(0x76 /* DecrementOp */);
 612    aml_append(var, arg);
 613    return var;
 614}
 615
 616/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIndex */
 617Aml *aml_index(Aml *arg1, Aml *idx)
 618{
 619    return build_opcode_2arg_dst(0x88 /* IndexOp */, arg1, idx, NULL);
 620}
 621
 622/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */
 623Aml *aml_notify(Aml *arg1, Aml *arg2)
 624{
 625    Aml *var = aml_opcode(0x86 /* NotifyOp */);
 626    aml_append(var, arg1);
 627    aml_append(var, arg2);
 628    return var;
 629}
 630
 631/* helper to call method without argument */
 632Aml *aml_call0(const char *method)
 633{
 634    Aml *var = aml_alloc();
 635    build_append_namestring(var->buf, "%s", method);
 636    return var;
 637}
 638
 639/* helper to call method with 1 argument */
 640Aml *aml_call1(const char *method, Aml *arg1)
 641{
 642    Aml *var = aml_alloc();
 643    build_append_namestring(var->buf, "%s", method);
 644    aml_append(var, arg1);
 645    return var;
 646}
 647
 648/* helper to call method with 2 arguments */
 649Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2)
 650{
 651    Aml *var = aml_alloc();
 652    build_append_namestring(var->buf, "%s", method);
 653    aml_append(var, arg1);
 654    aml_append(var, arg2);
 655    return var;
 656}
 657
 658/* helper to call method with 3 arguments */
 659Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3)
 660{
 661    Aml *var = aml_alloc();
 662    build_append_namestring(var->buf, "%s", method);
 663    aml_append(var, arg1);
 664    aml_append(var, arg2);
 665    aml_append(var, arg3);
 666    return var;
 667}
 668
 669/* helper to call method with 4 arguments */
 670Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4)
 671{
 672    Aml *var = aml_alloc();
 673    build_append_namestring(var->buf, "%s", method);
 674    aml_append(var, arg1);
 675    aml_append(var, arg2);
 676    aml_append(var, arg3);
 677    aml_append(var, arg4);
 678    return var;
 679}
 680
 681/* helper to call method with 5 arguments */
 682Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
 683               Aml *arg5)
 684{
 685    Aml *var = aml_alloc();
 686    build_append_namestring(var->buf, "%s", method);
 687    aml_append(var, arg1);
 688    aml_append(var, arg2);
 689    aml_append(var, arg3);
 690    aml_append(var, arg4);
 691    aml_append(var, arg5);
 692    return var;
 693}
 694
 695/*
 696 * ACPI 5.0: 6.4.3.8.1 GPIO Connection Descriptor
 697 * Type 1, Large Item Name 0xC
 698 */
 699
 700static Aml *aml_gpio_connection(AmlGpioConnectionType type,
 701                                AmlConsumerAndProducer con_and_pro,
 702                                uint8_t flags, AmlPinConfig pin_config,
 703                                uint16_t output_drive,
 704                                uint16_t debounce_timeout,
 705                                const uint32_t pin_list[], uint32_t pin_count,
 706                                const char *resource_source_name,
 707                                const uint8_t *vendor_data,
 708                                uint16_t vendor_data_len)
 709{
 710    Aml *var = aml_alloc();
 711    const uint16_t min_desc_len = 0x16;
 712    uint16_t resource_source_name_len, length;
 713    uint16_t pin_table_offset, resource_source_name_offset, vendor_data_offset;
 714    uint32_t i;
 715
 716    assert(resource_source_name);
 717    resource_source_name_len = strlen(resource_source_name) + 1;
 718    length = min_desc_len + resource_source_name_len + vendor_data_len;
 719    pin_table_offset = min_desc_len + 1;
 720    resource_source_name_offset = pin_table_offset + pin_count * 2;
 721    vendor_data_offset = resource_source_name_offset + resource_source_name_len;
 722
 723    build_append_byte(var->buf, 0x8C);  /* GPIO Connection Descriptor */
 724    build_append_int_noprefix(var->buf, length, 2); /* Length */
 725    build_append_byte(var->buf, 1);     /* Revision ID */
 726    build_append_byte(var->buf, type);  /* GPIO Connection Type */
 727    /* General Flags (2 bytes) */
 728    build_append_int_noprefix(var->buf, con_and_pro, 2);
 729    /* Interrupt and IO Flags (2 bytes) */
 730    build_append_int_noprefix(var->buf, flags, 2);
 731    /* Pin Configuration 0 = Default 1 = Pull-up 2 = Pull-down 3 = No Pull */
 732    build_append_byte(var->buf, pin_config);
 733    /* Output Drive Strength (2 bytes) */
 734    build_append_int_noprefix(var->buf, output_drive, 2);
 735    /* Debounce Timeout (2 bytes) */
 736    build_append_int_noprefix(var->buf, debounce_timeout, 2);
 737    /* Pin Table Offset (2 bytes) */
 738    build_append_int_noprefix(var->buf, pin_table_offset, 2);
 739    build_append_byte(var->buf, 0);     /* Resource Source Index */
 740    /* Resource Source Name Offset (2 bytes) */
 741    build_append_int_noprefix(var->buf, resource_source_name_offset, 2);
 742    /* Vendor Data Offset (2 bytes) */
 743    build_append_int_noprefix(var->buf, vendor_data_offset, 2);
 744    /* Vendor Data Length (2 bytes) */
 745    build_append_int_noprefix(var->buf, vendor_data_len, 2);
 746    /* Pin Number (2n bytes)*/
 747    for (i = 0; i < pin_count; i++) {
 748        build_append_int_noprefix(var->buf, pin_list[i], 2);
 749    }
 750
 751    /* Resource Source Name */
 752    build_append_namestring(var->buf, "%s", resource_source_name);
 753    build_append_byte(var->buf, '\0');
 754
 755    /* Vendor-defined Data */
 756    if (vendor_data != NULL) {
 757        g_array_append_vals(var->buf, vendor_data, vendor_data_len);
 758    }
 759
 760    return var;
 761}
 762
 763/*
 764 * ACPI 5.0: 19.5.53
 765 * GpioInt(GPIO Interrupt Connection Resource Descriptor Macro)
 766 */
 767Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro,
 768                  AmlLevelAndEdge edge_level,
 769                  AmlActiveHighAndLow active_level, AmlShared shared,
 770                  AmlPinConfig pin_config, uint16_t debounce_timeout,
 771                  const uint32_t pin_list[], uint32_t pin_count,
 772                  const char *resource_source_name,
 773                  const uint8_t *vendor_data, uint16_t vendor_data_len)
 774{
 775    uint8_t flags = edge_level | (active_level << 1) | (shared << 3);
 776
 777    return aml_gpio_connection(AML_INTERRUPT_CONNECTION, con_and_pro, flags,
 778                               pin_config, 0, debounce_timeout, pin_list,
 779                               pin_count, resource_source_name, vendor_data,
 780                               vendor_data_len);
 781}
 782
 783/*
 784 * ACPI 1.0b: 6.4.3.4 32-Bit Fixed Location Memory Range Descriptor
 785 * (Type 1, Large Item Name 0x6)
 786 */
 787Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
 788                        AmlReadAndWrite read_and_write)
 789{
 790    Aml *var = aml_alloc();
 791    build_append_byte(var->buf, 0x86); /* Memory32Fixed Resource Descriptor */
 792    build_append_byte(var->buf, 9);    /* Length, bits[7:0] value = 9 */
 793    build_append_byte(var->buf, 0);    /* Length, bits[15:8] value = 0 */
 794    build_append_byte(var->buf, read_and_write); /* Write status, 1 rw 0 ro */
 795
 796    /* Range base address */
 797    build_append_byte(var->buf, extract32(addr, 0, 8));  /* bits[7:0] */
 798    build_append_byte(var->buf, extract32(addr, 8, 8));  /* bits[15:8] */
 799    build_append_byte(var->buf, extract32(addr, 16, 8)); /* bits[23:16] */
 800    build_append_byte(var->buf, extract32(addr, 24, 8)); /* bits[31:24] */
 801
 802    /* Range length */
 803    build_append_byte(var->buf, extract32(size, 0, 8));  /* bits[7:0] */
 804    build_append_byte(var->buf, extract32(size, 8, 8));  /* bits[15:8] */
 805    build_append_byte(var->buf, extract32(size, 16, 8)); /* bits[23:16] */
 806    build_append_byte(var->buf, extract32(size, 24, 8)); /* bits[31:24] */
 807    return var;
 808}
 809
 810/*
 811 * ACPI 5.0: 6.4.3.6 Extended Interrupt Descriptor
 812 * Type 1, Large Item Name 0x9
 813 */
 814Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
 815                   AmlLevelAndEdge level_and_edge,
 816                   AmlActiveHighAndLow high_and_low, AmlShared shared,
 817                   uint32_t *irq_list, uint8_t irq_count)
 818{
 819    int i;
 820    Aml *var = aml_alloc();
 821    uint8_t irq_flags = con_and_pro | (level_and_edge << 1)
 822                        | (high_and_low << 2) | (shared << 3);
 823    const int header_bytes_in_len = 2;
 824    uint16_t len = header_bytes_in_len + irq_count * sizeof(uint32_t);
 825
 826    assert(irq_count > 0);
 827
 828    build_append_byte(var->buf, 0x89); /* Extended irq descriptor */
 829    build_append_byte(var->buf, len & 0xFF); /* Length, bits[7:0] */
 830    build_append_byte(var->buf, len >> 8); /* Length, bits[15:8] */
 831    build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */
 832    build_append_byte(var->buf, irq_count);   /* Interrupt table length */
 833
 834    /* Interrupt Number List */
 835    for (i = 0; i < irq_count; i++) {
 836        build_append_int_noprefix(var->buf, irq_list[i], 4);
 837    }
 838    return var;
 839}
 840
 841/* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */
 842Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
 843            uint8_t aln, uint8_t len)
 844{
 845    Aml *var = aml_alloc();
 846    build_append_byte(var->buf, 0x47); /* IO port descriptor */
 847    build_append_byte(var->buf, dec);
 848    build_append_byte(var->buf, min_base & 0xff);
 849    build_append_byte(var->buf, (min_base >> 8) & 0xff);
 850    build_append_byte(var->buf, max_base & 0xff);
 851    build_append_byte(var->buf, (max_base >> 8) & 0xff);
 852    build_append_byte(var->buf, aln);
 853    build_append_byte(var->buf, len);
 854    return var;
 855}
 856
 857/*
 858 * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor
 859 *
 860 * More verbose description at:
 861 * ACPI 5.0: 19.5.64 IRQNoFlags (Interrupt Resource Descriptor Macro)
 862 *           6.4.2.1 IRQ Descriptor
 863 */
 864Aml *aml_irq_no_flags(uint8_t irq)
 865{
 866    uint16_t irq_mask;
 867    Aml *var = aml_alloc();
 868
 869    assert(irq < 16);
 870    build_append_byte(var->buf, 0x22); /* IRQ descriptor 2 byte form */
 871
 872    irq_mask = 1U << irq;
 873    build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */
 874    build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */
 875    return var;
 876}
 877
 878/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLNot */
 879Aml *aml_lnot(Aml *arg)
 880{
 881    Aml *var = aml_opcode(0x92 /* LNotOp */);
 882    aml_append(var, arg);
 883    return var;
 884}
 885
 886/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */
 887Aml *aml_equal(Aml *arg1, Aml *arg2)
 888{
 889    Aml *var = aml_opcode(0x93 /* LequalOp */);
 890    aml_append(var, arg1);
 891    aml_append(var, arg2);
 892    return var;
 893}
 894
 895/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLGreater */
 896Aml *aml_lgreater(Aml *arg1, Aml *arg2)
 897{
 898    Aml *var = aml_opcode(0x94 /* LGreaterOp */);
 899    aml_append(var, arg1);
 900    aml_append(var, arg2);
 901    return var;
 902}
 903
 904/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLGreaterEqual */
 905Aml *aml_lgreater_equal(Aml *arg1, Aml *arg2)
 906{
 907    /* LGreaterEqualOp := LNotOp LLessOp */
 908    Aml *var = aml_opcode(0x92 /* LNotOp */);
 909    build_append_byte(var->buf, 0x95 /* LLessOp */);
 910    aml_append(var, arg1);
 911    aml_append(var, arg2);
 912    return var;
 913}
 914
 915/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefIfElse */
 916Aml *aml_if(Aml *predicate)
 917{
 918    Aml *var = aml_bundle(0xA0 /* IfOp */, AML_PACKAGE);
 919    aml_append(var, predicate);
 920    return var;
 921}
 922
 923/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefElse */
 924Aml *aml_else(void)
 925{
 926    Aml *var = aml_bundle(0xA1 /* ElseOp */, AML_PACKAGE);
 927    return var;
 928}
 929
 930/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefWhile */
 931Aml *aml_while(Aml *predicate)
 932{
 933    Aml *var = aml_bundle(0xA2 /* WhileOp */, AML_PACKAGE);
 934    aml_append(var, predicate);
 935    return var;
 936}
 937
 938/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
 939Aml *aml_method(const char *name, int arg_count, AmlSerializeFlag sflag)
 940{
 941    Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE);
 942    int methodflags;
 943
 944    /*
 945     * MethodFlags:
 946     *   bit 0-2: ArgCount (0-7)
 947     *   bit 3: SerializeFlag
 948     *     0: NotSerialized
 949     *     1: Serialized
 950     *   bit 4-7: reserved (must be 0)
 951     */
 952    assert(arg_count < 8);
 953    methodflags = arg_count | (sflag << 3);
 954
 955    build_append_namestring(var->buf, "%s", name);
 956    build_append_byte(var->buf, methodflags); /* MethodFlags: ArgCount */
 957    return var;
 958}
 959
 960/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */
 961Aml *aml_device(const char *name_format, ...)
 962{
 963    va_list ap;
 964    Aml *var = aml_bundle(0x82 /* DeviceOp */, AML_EXT_PACKAGE);
 965    va_start(ap, name_format);
 966    build_append_namestringv(var->buf, name_format, ap);
 967    va_end(ap);
 968    return var;
 969}
 970
 971/* ACPI 1.0b: 6.4.1 ASL Macros for Resource Descriptors */
 972Aml *aml_resource_template(void)
 973{
 974    /* ResourceTemplate is a buffer of Resources with EndTag at the end */
 975    Aml *var = aml_bundle(0x11 /* BufferOp */, AML_RES_TEMPLATE);
 976    return var;
 977}
 978
 979/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer
 980 * Pass byte_list as NULL to request uninitialized buffer to reserve space.
 981 */
 982Aml *aml_buffer(int buffer_size, uint8_t *byte_list)
 983{
 984    int i;
 985    Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
 986
 987    for (i = 0; i < buffer_size; i++) {
 988        if (byte_list == NULL) {
 989            build_append_byte(var->buf, 0x0);
 990        } else {
 991            build_append_byte(var->buf, byte_list[i]);
 992        }
 993    }
 994
 995    return var;
 996}
 997
 998/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefPackage */
 999Aml *aml_package(uint8_t num_elements)
1000{
1001    Aml *var = aml_bundle(0x12 /* PackageOp */, AML_PACKAGE);
1002    build_append_byte(var->buf, num_elements);
1003    return var;
1004}
1005
1006/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */
1007Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
1008                          Aml *offset, uint32_t len)
1009{
1010    Aml *var = aml_alloc();
1011    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1012    build_append_byte(var->buf, 0x80); /* OpRegionOp */
1013    build_append_namestring(var->buf, "%s", name);
1014    build_append_byte(var->buf, rs);
1015    aml_append(var, offset);
1016    build_append_int(var->buf, len);
1017    return var;
1018}
1019
1020/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */
1021Aml *aml_named_field(const char *name, unsigned length)
1022{
1023    Aml *var = aml_alloc();
1024    build_append_nameseg(var->buf, name);
1025    build_append_pkg_length(var->buf, length, false);
1026    return var;
1027}
1028
1029/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */
1030Aml *aml_reserved_field(unsigned length)
1031{
1032    Aml *var = aml_alloc();
1033    /* ReservedField  := 0x00 PkgLength */
1034    build_append_byte(var->buf, 0x00);
1035    build_append_pkg_length(var->buf, length, false);
1036    return var;
1037}
1038
1039/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */
1040Aml *aml_field(const char *name, AmlAccessType type, AmlLockRule lock,
1041               AmlUpdateRule rule)
1042{
1043    Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE);
1044    uint8_t flags = rule << 5 | type;
1045
1046    flags |= lock << 4; /* LockRule at 4 bit offset */
1047
1048    build_append_namestring(var->buf, "%s", name);
1049    build_append_byte(var->buf, flags);
1050    return var;
1051}
1052
1053static
1054Aml *create_field_common(int opcode, Aml *srcbuf, Aml *index, const char *name)
1055{
1056    Aml *var = aml_opcode(opcode);
1057    aml_append(var, srcbuf);
1058    aml_append(var, index);
1059    build_append_namestring(var->buf, "%s", name);
1060    return var;
1061}
1062
1063/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateField */
1064Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits,
1065                      const char *name)
1066{
1067    Aml *var = aml_alloc();
1068    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1069    build_append_byte(var->buf, 0x13); /* CreateFieldOp */
1070    aml_append(var, srcbuf);
1071    aml_append(var, bit_index);
1072    aml_append(var, num_bits);
1073    build_append_namestring(var->buf, "%s", name);
1074    return var;
1075}
1076
1077/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateDWordField */
1078Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name)
1079{
1080    return create_field_common(0x8A /* CreateDWordFieldOp */,
1081                               srcbuf, index, name);
1082}
1083
1084/* ACPI 2.0a: 17.2.4.2 Named Objects Encoding: DefCreateQWordField */
1085Aml *aml_create_qword_field(Aml *srcbuf, Aml *index, const char *name)
1086{
1087    return create_field_common(0x8F /* CreateQWordFieldOp */,
1088                               srcbuf, index, name);
1089}
1090
1091/* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */
1092Aml *aml_string(const char *name_format, ...)
1093{
1094    Aml *var = aml_opcode(0x0D /* StringPrefix */);
1095    va_list ap;
1096    char *s;
1097    int len;
1098
1099    va_start(ap, name_format);
1100    len = g_vasprintf(&s, name_format, ap);
1101    va_end(ap);
1102
1103    g_array_append_vals(var->buf, s, len + 1);
1104    g_free(s);
1105
1106    return var;
1107}
1108
1109/* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */
1110Aml *aml_local(int num)
1111{
1112    uint8_t op = 0x60 /* Local0Op */ + num;
1113
1114    assert(num <= 7);
1115    return aml_opcode(op);
1116}
1117
1118/* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */
1119Aml *aml_varpackage(uint32_t num_elements)
1120{
1121    Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE);
1122    build_append_int(var->buf, num_elements);
1123    return var;
1124}
1125
1126/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */
1127Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len,
1128                   const char *name_format, ...)
1129{
1130    va_list ap;
1131    Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE);
1132    va_start(ap, name_format);
1133    build_append_namestringv(var->buf, name_format, ap);
1134    va_end(ap);
1135    build_append_byte(var->buf, proc_id); /* ProcID */
1136    build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr));
1137    build_append_byte(var->buf, pblk_len); /* PblkLen */
1138    return var;
1139}
1140
1141static uint8_t Hex2Digit(char c)
1142{
1143    if (c >= 'A') {
1144        return c - 'A' + 10;
1145    }
1146
1147    return c - '0';
1148}
1149
1150/* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */
1151Aml *aml_eisaid(const char *str)
1152{
1153    Aml *var = aml_alloc();
1154    uint32_t id;
1155
1156    g_assert(strlen(str) == 7);
1157    id = (str[0] - 0x40) << 26 |
1158    (str[1] - 0x40) << 21 |
1159    (str[2] - 0x40) << 16 |
1160    Hex2Digit(str[3]) << 12 |
1161    Hex2Digit(str[4]) << 8 |
1162    Hex2Digit(str[5]) << 4 |
1163    Hex2Digit(str[6]);
1164
1165    build_append_byte(var->buf, 0x0C); /* DWordPrefix */
1166    build_append_int_noprefix(var->buf, bswap32(id), sizeof(id));
1167    return var;
1168}
1169
1170/* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */
1171static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed,
1172                               AmlMaxFixed max_fixed, AmlDecode dec,
1173                               uint8_t type_flags)
1174{
1175    uint8_t flags = max_fixed | min_fixed | dec;
1176    Aml *var = aml_alloc();
1177
1178    build_append_byte(var->buf, type);
1179    build_append_byte(var->buf, flags);
1180    build_append_byte(var->buf, type_flags); /* Type Specific Flags */
1181    return var;
1182}
1183
1184/* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */
1185static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
1186                             AmlMaxFixed max_fixed, AmlDecode dec,
1187                             uint16_t addr_gran, uint16_t addr_min,
1188                             uint16_t addr_max, uint16_t addr_trans,
1189                             uint16_t len, uint8_t type_flags)
1190{
1191    Aml *var = aml_alloc();
1192
1193    build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */
1194    /* minimum length since we do not encode optional fields */
1195    build_append_byte(var->buf, 0x0D);
1196    build_append_byte(var->buf, 0x0);
1197
1198    aml_append(var,
1199        aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
1200    build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
1201    build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
1202    build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
1203    build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
1204    build_append_int_noprefix(var->buf, len, sizeof(len));
1205    return var;
1206}
1207
1208/* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */
1209static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
1210                              AmlMaxFixed max_fixed, AmlDecode dec,
1211                              uint32_t addr_gran, uint32_t addr_min,
1212                              uint32_t addr_max, uint32_t addr_trans,
1213                              uint32_t len, uint8_t type_flags)
1214{
1215    Aml *var = aml_alloc();
1216
1217    build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */
1218    /* minimum length since we do not encode optional fields */
1219    build_append_byte(var->buf, 23);
1220    build_append_byte(var->buf, 0x0);
1221
1222
1223    aml_append(var,
1224        aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
1225    build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
1226    build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
1227    build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
1228    build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
1229    build_append_int_noprefix(var->buf, len, sizeof(len));
1230    return var;
1231}
1232
1233/* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */
1234static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
1235                              AmlMaxFixed max_fixed, AmlDecode dec,
1236                              uint64_t addr_gran, uint64_t addr_min,
1237                              uint64_t addr_max, uint64_t addr_trans,
1238                              uint64_t len, uint8_t type_flags)
1239{
1240    Aml *var = aml_alloc();
1241
1242    build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */
1243    /* minimum length since we do not encode optional fields */
1244    build_append_byte(var->buf, 0x2B);
1245    build_append_byte(var->buf, 0x0);
1246
1247    aml_append(var,
1248        aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
1249    build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
1250    build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
1251    build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
1252    build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
1253    build_append_int_noprefix(var->buf, len, sizeof(len));
1254    return var;
1255}
1256
1257/*
1258 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
1259 *
1260 * More verbose description at:
1261 * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro)
1262 */
1263Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
1264                         AmlDecode dec, uint16_t addr_gran,
1265                         uint16_t addr_min, uint16_t addr_max,
1266                         uint16_t addr_trans, uint16_t len)
1267
1268{
1269    return aml_word_as_desc(AML_BUS_NUMBER_RANGE, min_fixed, max_fixed, dec,
1270                            addr_gran, addr_min, addr_max, addr_trans, len, 0);
1271}
1272
1273/*
1274 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
1275 *
1276 * More verbose description at:
1277 * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro)
1278 */
1279Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
1280                 AmlDecode dec, AmlISARanges isa_ranges,
1281                 uint16_t addr_gran, uint16_t addr_min,
1282                 uint16_t addr_max, uint16_t addr_trans,
1283                 uint16_t len)
1284
1285{
1286    return aml_word_as_desc(AML_IO_RANGE, min_fixed, max_fixed, dec,
1287                            addr_gran, addr_min, addr_max, addr_trans, len,
1288                            isa_ranges);
1289}
1290
1291/*
1292 * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Descriptor
1293 *
1294 * More verbose description at:
1295 * ACPI 5.0: 19.5.33 DWordIO (DWord IO Resource Descriptor Macro)
1296 */
1297Aml *aml_dword_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
1298                 AmlDecode dec, AmlISARanges isa_ranges,
1299                 uint32_t addr_gran, uint32_t addr_min,
1300                 uint32_t addr_max, uint32_t addr_trans,
1301                 uint32_t len)
1302
1303{
1304    return aml_dword_as_desc(AML_IO_RANGE, min_fixed, max_fixed, dec,
1305                            addr_gran, addr_min, addr_max, addr_trans, len,
1306                            isa_ranges);
1307}
1308
1309/*
1310 * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor
1311 *
1312 * More verbose description at:
1313 * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro)
1314 */
1315Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
1316                      AmlMaxFixed max_fixed, AmlCacheable cacheable,
1317                      AmlReadAndWrite read_and_write,
1318                      uint32_t addr_gran, uint32_t addr_min,
1319                      uint32_t addr_max, uint32_t addr_trans,
1320                      uint32_t len)
1321{
1322    uint8_t flags = read_and_write | (cacheable << 1);
1323
1324    return aml_dword_as_desc(AML_MEMORY_RANGE, min_fixed, max_fixed,
1325                             dec, addr_gran, addr_min, addr_max,
1326                             addr_trans, len, flags);
1327}
1328
1329/*
1330 * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor
1331 *
1332 * More verbose description at:
1333 * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro)
1334 */
1335Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
1336                      AmlMaxFixed max_fixed, AmlCacheable cacheable,
1337                      AmlReadAndWrite read_and_write,
1338                      uint64_t addr_gran, uint64_t addr_min,
1339                      uint64_t addr_max, uint64_t addr_trans,
1340                      uint64_t len)
1341{
1342    uint8_t flags = read_and_write | (cacheable << 1);
1343
1344    return aml_qword_as_desc(AML_MEMORY_RANGE, min_fixed, max_fixed,
1345                             dec, addr_gran, addr_min, addr_max,
1346                             addr_trans, len, flags);
1347}
1348
1349/* ACPI 1.0b: 6.4.2.2 DMA Format/6.4.2.2.1 ASL Macro for DMA Descriptor */
1350Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
1351             uint8_t channel)
1352{
1353    Aml *var = aml_alloc();
1354    uint8_t flags = sz | bm << 2 | typ << 5;
1355
1356    assert(channel < 8);
1357    build_append_byte(var->buf, 0x2A);    /* Byte 0: DMA Descriptor */
1358    build_append_byte(var->buf, 1U << channel); /* Byte 1: _DMA - DmaChannel */
1359    build_append_byte(var->buf, flags);   /* Byte 2 */
1360    return var;
1361}
1362
1363/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefSleep */
1364Aml *aml_sleep(uint64_t msec)
1365{
1366    Aml *var = aml_alloc();
1367    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1368    build_append_byte(var->buf, 0x22); /* SleepOp */
1369    aml_append(var, aml_int(msec));
1370    return var;
1371}
1372
1373static uint8_t Hex2Byte(const char *src)
1374{
1375    int hi, lo;
1376
1377    hi = Hex2Digit(src[0]);
1378    assert(hi >= 0);
1379    assert(hi <= 15);
1380
1381    lo = Hex2Digit(src[1]);
1382    assert(lo >= 0);
1383    assert(lo <= 15);
1384    return (hi << 4) | lo;
1385}
1386
1387/*
1388 * ACPI 3.0: 17.5.124 ToUUID (Convert String to UUID Macro)
1389 * e.g. UUID: aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
1390 * call aml_touuid("aabbccdd-eeff-gghh-iijj-kkllmmnnoopp");
1391 */
1392Aml *aml_touuid(const char *uuid)
1393{
1394    Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
1395
1396    assert(strlen(uuid) == 36);
1397    assert(uuid[8] == '-');
1398    assert(uuid[13] == '-');
1399    assert(uuid[18] == '-');
1400    assert(uuid[23] == '-');
1401
1402    build_append_byte(var->buf, Hex2Byte(uuid + 6));  /* dd - at offset 00 */
1403    build_append_byte(var->buf, Hex2Byte(uuid + 4));  /* cc - at offset 01 */
1404    build_append_byte(var->buf, Hex2Byte(uuid + 2));  /* bb - at offset 02 */
1405    build_append_byte(var->buf, Hex2Byte(uuid + 0));  /* aa - at offset 03 */
1406
1407    build_append_byte(var->buf, Hex2Byte(uuid + 11)); /* ff - at offset 04 */
1408    build_append_byte(var->buf, Hex2Byte(uuid + 9));  /* ee - at offset 05 */
1409
1410    build_append_byte(var->buf, Hex2Byte(uuid + 16)); /* hh - at offset 06 */
1411    build_append_byte(var->buf, Hex2Byte(uuid + 14)); /* gg - at offset 07 */
1412
1413    build_append_byte(var->buf, Hex2Byte(uuid + 19)); /* ii - at offset 08 */
1414    build_append_byte(var->buf, Hex2Byte(uuid + 21)); /* jj - at offset 09 */
1415
1416    build_append_byte(var->buf, Hex2Byte(uuid + 24)); /* kk - at offset 10 */
1417    build_append_byte(var->buf, Hex2Byte(uuid + 26)); /* ll - at offset 11 */
1418    build_append_byte(var->buf, Hex2Byte(uuid + 28)); /* mm - at offset 12 */
1419    build_append_byte(var->buf, Hex2Byte(uuid + 30)); /* nn - at offset 13 */
1420    build_append_byte(var->buf, Hex2Byte(uuid + 32)); /* oo - at offset 14 */
1421    build_append_byte(var->buf, Hex2Byte(uuid + 34)); /* pp - at offset 15 */
1422
1423    return var;
1424}
1425
1426/*
1427 * ACPI 2.0b: 16.2.3.6.4.3  Unicode Macro (Convert Ascii String To Unicode)
1428 */
1429Aml *aml_unicode(const char *str)
1430{
1431    int i = 0;
1432    Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
1433
1434    do {
1435        build_append_byte(var->buf, str[i]);
1436        build_append_byte(var->buf, 0);
1437        i++;
1438    } while (i <= strlen(str));
1439
1440    return var;
1441}
1442
1443/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefRefOf */
1444Aml *aml_refof(Aml *arg)
1445{
1446    Aml *var = aml_opcode(0x71 /* RefOfOp */);
1447    aml_append(var, arg);
1448    return var;
1449}
1450
1451/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
1452Aml *aml_derefof(Aml *arg)
1453{
1454    Aml *var = aml_opcode(0x83 /* DerefOfOp */);
1455    aml_append(var, arg);
1456    return var;
1457}
1458
1459/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefSizeOf */
1460Aml *aml_sizeof(Aml *arg)
1461{
1462    Aml *var = aml_opcode(0x87 /* SizeOfOp */);
1463    aml_append(var, arg);
1464    return var;
1465}
1466
1467/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMutex */
1468Aml *aml_mutex(const char *name, uint8_t sync_level)
1469{
1470    Aml *var = aml_alloc();
1471    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1472    build_append_byte(var->buf, 0x01); /* MutexOp */
1473    build_append_namestring(var->buf, "%s", name);
1474    assert(!(sync_level & 0xF0));
1475    build_append_byte(var->buf, sync_level);
1476    return var;
1477}
1478
1479/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAcquire */
1480Aml *aml_acquire(Aml *mutex, uint16_t timeout)
1481{
1482    Aml *var = aml_alloc();
1483    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1484    build_append_byte(var->buf, 0x23); /* AcquireOp */
1485    aml_append(var, mutex);
1486    build_append_int_noprefix(var->buf, timeout, sizeof(timeout));
1487    return var;
1488}
1489
1490/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefRelease */
1491Aml *aml_release(Aml *mutex)
1492{
1493    Aml *var = aml_alloc();
1494    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1495    build_append_byte(var->buf, 0x27); /* ReleaseOp */
1496    aml_append(var, mutex);
1497    return var;
1498}
1499
1500/* ACPI 1.0b: 16.2.5.1 Name Space Modifier Objects Encoding: DefAlias */
1501Aml *aml_alias(const char *source_object, const char *alias_object)
1502{
1503    Aml *var = aml_opcode(0x06 /* AliasOp */);
1504    aml_append(var, aml_name("%s", source_object));
1505    aml_append(var, aml_name("%s", alias_object));
1506    return var;
1507}
1508
1509/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefConcat */
1510Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
1511{
1512    return build_opcode_2arg_dst(0x73 /* ConcatOp */, source1, source2,
1513                                 target);
1514}
1515
1516/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefObjectType */
1517Aml *aml_object_type(Aml *object)
1518{
1519    Aml *var = aml_opcode(0x8E /* ObjectTypeOp */);
1520    aml_append(var, object);
1521    return var;
1522}
1523
1524void
1525build_header(BIOSLinker *linker, GArray *table_data,
1526             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
1527             const char *oem_id, const char *oem_table_id)
1528{
1529    unsigned tbl_offset = (char *)h - table_data->data;
1530    unsigned checksum_offset = (char *)&h->checksum - table_data->data;
1531    memcpy(&h->signature, sig, 4);
1532    h->length = cpu_to_le32(len);
1533    h->revision = rev;
1534
1535    if (oem_id) {
1536        strncpy((char *)h->oem_id, oem_id, sizeof h->oem_id);
1537    } else {
1538        memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
1539    }
1540
1541    if (oem_table_id) {
1542        strncpy((char *)h->oem_table_id, oem_table_id, sizeof(h->oem_table_id));
1543    } else {
1544        memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
1545        memcpy(h->oem_table_id + 4, sig, 4);
1546    }
1547
1548    h->oem_revision = cpu_to_le32(1);
1549    memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
1550    h->asl_compiler_revision = cpu_to_le32(1);
1551    /* Checksum to be filled in by Guest linker */
1552    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
1553        tbl_offset, len, checksum_offset);
1554}
1555
1556void *acpi_data_push(GArray *table_data, unsigned size)
1557{
1558    unsigned off = table_data->len;
1559    g_array_set_size(table_data, off + size);
1560    return table_data->data + off;
1561}
1562
1563unsigned acpi_data_len(GArray *table)
1564{
1565    assert(g_array_get_element_size(table) == 1);
1566    return table->len;
1567}
1568
1569void acpi_add_table(GArray *table_offsets, GArray *table_data)
1570{
1571    uint32_t offset = table_data->len;
1572    g_array_append_val(table_offsets, offset);
1573}
1574
1575void acpi_build_tables_init(AcpiBuildTables *tables)
1576{
1577    tables->rsdp = g_array_new(false, true /* clear */, 1);
1578    tables->table_data = g_array_new(false, true /* clear */, 1);
1579    tables->tcpalog = g_array_new(false, true /* clear */, 1);
1580    tables->vmgenid = g_array_new(false, true /* clear */, 1);
1581    tables->linker = bios_linker_loader_init();
1582}
1583
1584void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
1585{
1586    bios_linker_loader_cleanup(tables->linker);
1587    g_array_free(tables->rsdp, true);
1588    g_array_free(tables->table_data, true);
1589    g_array_free(tables->tcpalog, mfre);
1590    g_array_free(tables->vmgenid, mfre);
1591}
1592
1593/*
1594 * ACPI spec 5.2.5.3 Root System Description Pointer (RSDP).
1595 * (Revision 1.0 or later)
1596 */
1597void
1598build_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data)
1599{
1600    int tbl_off = tbl->len; /* Table offset in the RSDP file */
1601
1602    switch (rsdp_data->revision) {
1603    case 0:
1604        /* With ACPI 1.0, we must have an RSDT pointer */
1605        g_assert(rsdp_data->rsdt_tbl_offset);
1606        break;
1607    case 2:
1608        /* With ACPI 2.0+, we must have an XSDT pointer */
1609        g_assert(rsdp_data->xsdt_tbl_offset);
1610        break;
1611    default:
1612        /* Only revisions 0 (ACPI 1.0) and 2 (ACPI 2.0+) are valid for RSDP */
1613        g_assert_not_reached();
1614    }
1615
1616    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, tbl, 16,
1617                             true /* fseg memory */);
1618
1619    g_array_append_vals(tbl, "RSD PTR ", 8); /* Signature */
1620    build_append_int_noprefix(tbl, 0, 1); /* Checksum */
1621    g_array_append_vals(tbl, rsdp_data->oem_id, 6); /* OEMID */
1622    build_append_int_noprefix(tbl, rsdp_data->revision, 1); /* Revision */
1623    build_append_int_noprefix(tbl, 0, 4); /* RsdtAddress */
1624    if (rsdp_data->rsdt_tbl_offset) {
1625        /* RSDT address to be filled by guest linker */
1626        bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
1627                                       tbl_off + 16, 4,
1628                                       ACPI_BUILD_TABLE_FILE,
1629                                       *rsdp_data->rsdt_tbl_offset);
1630    }
1631
1632    /* Checksum to be filled by guest linker */
1633    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
1634                                    tbl_off, 20, /* ACPI rev 1.0 RSDP size */
1635                                    8);
1636
1637    if (rsdp_data->revision == 0) {
1638        /* ACPI 1.0 RSDP, we're done */
1639        return;
1640    }
1641
1642    build_append_int_noprefix(tbl, 36, 4); /* Length */
1643
1644    /* XSDT address to be filled by guest linker */
1645    build_append_int_noprefix(tbl, 0, 8); /* XsdtAddress */
1646    /* We already validated our xsdt pointer */
1647    bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
1648                                   tbl_off + 24, 8,
1649                                   ACPI_BUILD_TABLE_FILE,
1650                                   *rsdp_data->xsdt_tbl_offset);
1651
1652    build_append_int_noprefix(tbl, 0, 1); /* Extended Checksum */
1653    build_append_int_noprefix(tbl, 0, 3); /* Reserved */
1654
1655    /* Extended checksum to be filled by Guest linker */
1656    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
1657                                    tbl_off, 36, /* ACPI rev 2.0 RSDP size */
1658                                    32);
1659}
1660
1661/* Build rsdt table */
1662void
1663build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
1664           const char *oem_id, const char *oem_table_id)
1665{
1666    int i;
1667    unsigned rsdt_entries_offset;
1668    AcpiRsdtDescriptorRev1 *rsdt;
1669    const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len);
1670    const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]);
1671    const size_t rsdt_len = sizeof(*rsdt) + table_data_len;
1672
1673    rsdt = acpi_data_push(table_data, rsdt_len);
1674    rsdt_entries_offset = (char *)rsdt->table_offset_entry - table_data->data;
1675    for (i = 0; i < table_offsets->len; ++i) {
1676        uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
1677        uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i;
1678
1679        /* rsdt->table_offset_entry to be filled by Guest linker */
1680        bios_linker_loader_add_pointer(linker,
1681            ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, rsdt_entry_size,
1682            ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
1683    }
1684    build_header(linker, table_data,
1685                 (void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
1686}
1687
1688/* Build xsdt table */
1689void
1690build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
1691           const char *oem_id, const char *oem_table_id)
1692{
1693    int i;
1694    unsigned xsdt_entries_offset;
1695    AcpiXsdtDescriptorRev2 *xsdt;
1696    const unsigned table_data_len = (sizeof(uint64_t) * table_offsets->len);
1697    const unsigned xsdt_entry_size = sizeof(xsdt->table_offset_entry[0]);
1698    const size_t xsdt_len = sizeof(*xsdt) + table_data_len;
1699
1700    xsdt = acpi_data_push(table_data, xsdt_len);
1701    xsdt_entries_offset = (char *)xsdt->table_offset_entry - table_data->data;
1702    for (i = 0; i < table_offsets->len; ++i) {
1703        uint64_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
1704        uint64_t xsdt_entry_offset = xsdt_entries_offset + xsdt_entry_size * i;
1705
1706        /* xsdt->table_offset_entry to be filled by Guest linker */
1707        bios_linker_loader_add_pointer(linker,
1708            ACPI_BUILD_TABLE_FILE, xsdt_entry_offset, xsdt_entry_size,
1709            ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
1710    }
1711    build_header(linker, table_data,
1712                 (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id);
1713}
1714
1715void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
1716                       uint64_t len, int node, MemoryAffinityFlags flags)
1717{
1718    numamem->type = ACPI_SRAT_MEMORY;
1719    numamem->length = sizeof(*numamem);
1720    numamem->proximity = cpu_to_le32(node);
1721    numamem->flags = cpu_to_le32(flags);
1722    numamem->base_addr = cpu_to_le64(base);
1723    numamem->range_length = cpu_to_le64(len);
1724}
1725
1726/*
1727 * ACPI spec 5.2.17 System Locality Distance Information Table
1728 * (Revision 2.0 or later)
1729 */
1730void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms)
1731{
1732    int slit_start, i, j;
1733    slit_start = table_data->len;
1734    int nb_numa_nodes = ms->numa_state->num_nodes;
1735
1736    acpi_data_push(table_data, sizeof(AcpiTableHeader));
1737
1738    build_append_int_noprefix(table_data, nb_numa_nodes, 8);
1739    for (i = 0; i < nb_numa_nodes; i++) {
1740        for (j = 0; j < nb_numa_nodes; j++) {
1741            assert(ms->numa_state->nodes[i].distance[j]);
1742            build_append_int_noprefix(table_data,
1743                                      ms->numa_state->nodes[i].distance[j],
1744                                      1);
1745        }
1746    }
1747
1748    build_header(linker, table_data,
1749                 (void *)(table_data->data + slit_start),
1750                 "SLIT",
1751                 table_data->len - slit_start, 1, NULL, NULL);
1752}
1753
1754/* build rev1/rev3/rev5.1 FADT */
1755void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
1756                const char *oem_id, const char *oem_table_id)
1757{
1758    int off;
1759    int fadt_start = tbl->len;
1760
1761    acpi_data_push(tbl, sizeof(AcpiTableHeader));
1762
1763    /* FACS address to be filled by Guest linker at runtime */
1764    off = tbl->len;
1765    build_append_int_noprefix(tbl, 0, 4); /* FIRMWARE_CTRL */
1766    if (f->facs_tbl_offset) { /* don't patch if not supported by platform */
1767        bios_linker_loader_add_pointer(linker,
1768            ACPI_BUILD_TABLE_FILE, off, 4,
1769            ACPI_BUILD_TABLE_FILE, *f->facs_tbl_offset);
1770    }
1771
1772    /* DSDT address to be filled by Guest linker at runtime */
1773    off = tbl->len;
1774    build_append_int_noprefix(tbl, 0, 4); /* DSDT */
1775    if (f->dsdt_tbl_offset) { /* don't patch if not supported by platform */
1776        bios_linker_loader_add_pointer(linker,
1777            ACPI_BUILD_TABLE_FILE, off, 4,
1778            ACPI_BUILD_TABLE_FILE, *f->dsdt_tbl_offset);
1779    }
1780
1781    /* ACPI1.0: INT_MODEL, ACPI2.0+: Reserved */
1782    build_append_int_noprefix(tbl, f->int_model /* Multiple APIC */, 1);
1783    /* Preferred_PM_Profile */
1784    build_append_int_noprefix(tbl, 0 /* Unspecified */, 1);
1785    build_append_int_noprefix(tbl, f->sci_int, 2); /* SCI_INT */
1786    build_append_int_noprefix(tbl, f->smi_cmd, 4); /* SMI_CMD */
1787    build_append_int_noprefix(tbl, f->acpi_enable_cmd, 1); /* ACPI_ENABLE */
1788    build_append_int_noprefix(tbl, f->acpi_disable_cmd, 1); /* ACPI_DISABLE */
1789    build_append_int_noprefix(tbl, 0 /* not supported */, 1); /* S4BIOS_REQ */
1790    /* ACPI1.0: Reserved, ACPI2.0+: PSTATE_CNT */
1791    build_append_int_noprefix(tbl, 0, 1);
1792    build_append_int_noprefix(tbl, f->pm1a_evt.address, 4); /* PM1a_EVT_BLK */
1793    build_append_int_noprefix(tbl, 0, 4); /* PM1b_EVT_BLK */
1794    build_append_int_noprefix(tbl, f->pm1a_cnt.address, 4); /* PM1a_CNT_BLK */
1795    build_append_int_noprefix(tbl, 0, 4); /* PM1b_CNT_BLK */
1796    build_append_int_noprefix(tbl, 0, 4); /* PM2_CNT_BLK */
1797    build_append_int_noprefix(tbl, f->pm_tmr.address, 4); /* PM_TMR_BLK */
1798    build_append_int_noprefix(tbl, f->gpe0_blk.address, 4); /* GPE0_BLK */
1799    build_append_int_noprefix(tbl, 0, 4); /* GPE1_BLK */
1800    /* PM1_EVT_LEN */
1801    build_append_int_noprefix(tbl, f->pm1a_evt.bit_width / 8, 1);
1802    /* PM1_CNT_LEN */
1803    build_append_int_noprefix(tbl, f->pm1a_cnt.bit_width / 8, 1);
1804    build_append_int_noprefix(tbl, 0, 1); /* PM2_CNT_LEN */
1805    build_append_int_noprefix(tbl, f->pm_tmr.bit_width / 8, 1); /* PM_TMR_LEN */
1806    /* GPE0_BLK_LEN */
1807    build_append_int_noprefix(tbl, f->gpe0_blk.bit_width / 8, 1);
1808    build_append_int_noprefix(tbl, 0, 1); /* GPE1_BLK_LEN */
1809    build_append_int_noprefix(tbl, 0, 1); /* GPE1_BASE */
1810    build_append_int_noprefix(tbl, 0, 1); /* CST_CNT */
1811    build_append_int_noprefix(tbl, f->plvl2_lat, 2); /* P_LVL2_LAT */
1812    build_append_int_noprefix(tbl, f->plvl3_lat, 2); /* P_LVL3_LAT */
1813    build_append_int_noprefix(tbl, 0, 2); /* FLUSH_SIZE */
1814    build_append_int_noprefix(tbl, 0, 2); /* FLUSH_STRIDE */
1815    build_append_int_noprefix(tbl, 0, 1); /* DUTY_OFFSET */
1816    build_append_int_noprefix(tbl, 0, 1); /* DUTY_WIDTH */
1817    build_append_int_noprefix(tbl, 0, 1); /* DAY_ALRM */
1818    build_append_int_noprefix(tbl, 0, 1); /* MON_ALRM */
1819    build_append_int_noprefix(tbl, f->rtc_century, 1); /* CENTURY */
1820    build_append_int_noprefix(tbl, 0, 2); /* IAPC_BOOT_ARCH */
1821    build_append_int_noprefix(tbl, 0, 1); /* Reserved */
1822    build_append_int_noprefix(tbl, f->flags, 4); /* Flags */
1823
1824    if (f->rev == 1) {
1825        goto build_hdr;
1826    }
1827
1828    build_append_gas_from_struct(tbl, &f->reset_reg); /* RESET_REG */
1829    build_append_int_noprefix(tbl, f->reset_val, 1); /* RESET_VALUE */
1830    /* Since ACPI 5.1 */
1831    if ((f->rev >= 6) || ((f->rev == 5) && f->minor_ver > 0)) {
1832        build_append_int_noprefix(tbl, f->arm_boot_arch, 2); /* ARM_BOOT_ARCH */
1833        /* FADT Minor Version */
1834        build_append_int_noprefix(tbl, f->minor_ver, 1);
1835    } else {
1836        build_append_int_noprefix(tbl, 0, 3); /* Reserved upto ACPI 5.0 */
1837    }
1838    build_append_int_noprefix(tbl, 0, 8); /* X_FIRMWARE_CTRL */
1839
1840    /* XDSDT address to be filled by Guest linker at runtime */
1841    off = tbl->len;
1842    build_append_int_noprefix(tbl, 0, 8); /* X_DSDT */
1843    if (f->xdsdt_tbl_offset) {
1844        bios_linker_loader_add_pointer(linker,
1845            ACPI_BUILD_TABLE_FILE, off, 8,
1846            ACPI_BUILD_TABLE_FILE, *f->xdsdt_tbl_offset);
1847    }
1848
1849    build_append_gas_from_struct(tbl, &f->pm1a_evt); /* X_PM1a_EVT_BLK */
1850    /* X_PM1b_EVT_BLK */
1851    build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
1852    build_append_gas_from_struct(tbl, &f->pm1a_cnt); /* X_PM1a_CNT_BLK */
1853    /* X_PM1b_CNT_BLK */
1854    build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
1855    /* X_PM2_CNT_BLK */
1856    build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
1857    build_append_gas_from_struct(tbl, &f->pm_tmr); /* X_PM_TMR_BLK */
1858    build_append_gas_from_struct(tbl, &f->gpe0_blk); /* X_GPE0_BLK */
1859    build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0); /* X_GPE1_BLK */
1860
1861    if (f->rev <= 4) {
1862        goto build_hdr;
1863    }
1864
1865    /* SLEEP_CONTROL_REG */
1866    build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
1867    /* SLEEP_STATUS_REG */
1868    build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
1869
1870    /* TODO: extra fields need to be added to support revisions above rev5 */
1871    assert(f->rev == 5);
1872
1873build_hdr:
1874    build_header(linker, tbl, (void *)(tbl->data + fadt_start),
1875                 "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
1876}
1877
1878/* ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors */
1879static Aml *aml_serial_bus_device(uint8_t serial_bus_type, uint8_t flags,
1880                                  uint16_t type_flags,
1881                                  uint8_t revid, uint16_t data_length,
1882                                  uint16_t resource_source_len)
1883{
1884    Aml *var = aml_alloc();
1885    uint16_t length = data_length + resource_source_len + 9;
1886
1887    build_append_byte(var->buf, 0x8e); /* Serial Bus Connection Descriptor */
1888    build_append_int_noprefix(var->buf, length, sizeof(length));
1889    build_append_byte(var->buf, 1);    /* Revision ID */
1890    build_append_byte(var->buf, 0);    /* Resource Source Index */
1891    build_append_byte(var->buf, serial_bus_type); /* Serial Bus Type */
1892    build_append_byte(var->buf, flags); /* General Flags */
1893    build_append_int_noprefix(var->buf, type_flags, /* Type Specific Flags */
1894                              sizeof(type_flags));
1895    build_append_byte(var->buf, revid); /* Type Specification Revision ID */
1896    build_append_int_noprefix(var->buf, data_length, sizeof(data_length));
1897
1898    return var;
1899}
1900
1901/* ACPI 5.0: 6.4.3.8.2.1 I2C Serial Bus Connection Resource Descriptor */
1902Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source)
1903{
1904    uint16_t resource_source_len = strlen(resource_source) + 1;
1905    Aml *var = aml_serial_bus_device(AML_SERIAL_BUS_TYPE_I2C, 0, 0, 1,
1906                                     6, resource_source_len);
1907
1908    /* Connection Speed.  Just set to 100K for now, it doesn't really matter. */
1909    build_append_int_noprefix(var->buf, 100000, 4);
1910    build_append_int_noprefix(var->buf, address, sizeof(address));
1911
1912    /* This is a string, not a name, so just copy it directly in. */
1913    g_array_append_vals(var->buf, resource_source, resource_source_len);
1914
1915    return var;
1916}
1917