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 30 static GArray *build_alloc_array(void) 31 { 32 return g_array_new(false, true /* clear */, 1); 33 } 34 35 static void build_free_array(GArray *array) 36 { 37 g_array_free(array, true); 38 } 39 40 static void build_prepend_byte(GArray *array, uint8_t val) 41 { 42 g_array_prepend_val(array, val); 43 } 44 45 static void build_append_byte(GArray *array, uint8_t val) 46 { 47 g_array_append_val(array, val); 48 } 49 50 static 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 57 static void 58 build_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 70 static void GCC_FMT_ATTR(2, 0) 71 build_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 133 GCC_FMT_ATTR(2, 3) 134 static 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 */ 144 enum { 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 151 static void 152 build_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 209 static void 210 build_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 219 static 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 225 static void build_extop_package(GArray *package, uint8_t op) 226 { 227 build_package(package, op); 228 build_prepend_byte(package, 0x5B); /* ExtOpPrefix */ 229 } 230 231 void 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 241 static 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 */ 267 void 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 */ 286 int 287 build_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 306 static GPtrArray *alloc_list; 307 308 static 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 318 static 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 327 static 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 336 static 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 343 Aml *init_aml_allocator(void) 344 { 345 assert(!alloc_list); 346 alloc_list = g_ptr_array_new(); 347 return aml_alloc(); 348 } 349 350 void 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 */ 358 static 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 368 void 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 */ 405 Aml *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 */ 416 Aml *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 */ 424 Aml *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 */ 436 Aml *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 */ 447 Aml *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 */ 458 Aml *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 */ 467 Aml *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 */ 476 Aml *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 */ 485 Aml *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 */ 498 Aml *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 */ 511 Aml *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 */ 532 static Aml * 533 build_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 */ 547 Aml *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 */ 553 Aml *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 */ 559 Aml *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 */ 568 Aml *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 */ 574 Aml *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 */ 580 Aml *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 */ 589 Aml *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 */ 595 Aml *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 */ 601 Aml *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 */ 609 Aml *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 */ 617 Aml *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 */ 623 Aml *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 */ 632 Aml *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 */ 640 Aml *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 */ 649 Aml *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 */ 659 Aml *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 */ 670 Aml *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 */ 682 Aml *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 700 static 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 */ 767 Aml *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 */ 787 Aml *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 */ 814 Aml *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 */ 842 Aml *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 */ 864 Aml *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 */ 879 Aml *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 */ 887 Aml *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 */ 896 Aml *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 */ 905 Aml *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 */ 916 Aml *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 */ 924 Aml *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 */ 931 Aml *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 */ 939 Aml *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 */ 961 Aml *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 */ 972 Aml *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 */ 982 Aml *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 */ 999 Aml *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 */ 1007 Aml *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 */ 1021 Aml *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 */ 1030 Aml *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 */ 1040 Aml *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 1053 static 1054 Aml *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 */ 1064 Aml *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 */ 1078 Aml *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 */ 1085 Aml *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 */ 1092 Aml *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 */ 1110 Aml *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 */ 1119 Aml *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 */ 1127 Aml *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 1141 static 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 */ 1151 Aml *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 */ 1171 static 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 */ 1185 static 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 */ 1209 static 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 */ 1234 static 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 */ 1263 Aml *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 */ 1279 Aml *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 */ 1297 Aml *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 */ 1315 Aml *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 */ 1335 Aml *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 */ 1350 Aml *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 */ 1364 Aml *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 1373 static 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 */ 1392 Aml *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 */ 1429 Aml *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 */ 1444 Aml *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 */ 1452 Aml *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 */ 1460 Aml *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 */ 1468 Aml *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 */ 1480 Aml *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 */ 1491 Aml *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 */ 1501 Aml *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 */ 1510 Aml *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 */ 1517 Aml *aml_object_type(Aml *object) 1518 { 1519 Aml *var = aml_opcode(0x8E /* ObjectTypeOp */); 1520 aml_append(var, object); 1521 return var; 1522 } 1523 1524 void 1525 build_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 1556 void *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 1563 unsigned acpi_data_len(GArray *table) 1564 { 1565 assert(g_array_get_element_size(table) == 1); 1566 return table->len; 1567 } 1568 1569 void 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 1575 void 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 1584 void 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 */ 1597 void 1598 build_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 */ 1662 void 1663 build_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 */ 1689 void 1690 build_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 1715 void 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 */ 1730 void 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 */ 1755 void 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 1873 build_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