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