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 <stdio.h> 23 #include <stdarg.h> 24 #include <assert.h> 25 #include <stdbool.h> 26 #include <string.h> 27 #include "hw/acpi/aml-build.h" 28 #include "qemu/bswap.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 /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */ 61 int len; 62 63 len = strlen(seg); 64 assert(len <= ACPI_NAMESEG_LEN); 65 66 g_array_append_vals(array, seg, len); 67 /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */ 68 g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len); 69 } 70 71 static void 72 build_append_namestringv(GArray *array, const char *format, va_list ap) 73 { 74 /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */ 75 char *s; 76 int len; 77 va_list va_len; 78 char **segs; 79 char **segs_iter; 80 int seg_count = 0; 81 82 va_copy(va_len, ap); 83 len = vsnprintf(NULL, 0, format, va_len); 84 va_end(va_len); 85 len += 1; 86 s = g_new(typeof(*s), len); 87 88 len = vsnprintf(s, len, format, ap); 89 90 segs = g_strsplit(s, ".", 0); 91 g_free(s); 92 93 /* count segments */ 94 segs_iter = segs; 95 while (*segs_iter) { 96 ++segs_iter; 97 ++seg_count; 98 } 99 /* 100 * ACPI 5.0 spec: 20.2.2 Name Objects Encoding: 101 * "SegCount can be from 1 to 255" 102 */ 103 assert(seg_count > 0 && seg_count <= 255); 104 105 /* handle RootPath || PrefixPath */ 106 s = *segs; 107 while (*s == '\\' || *s == '^') { 108 build_append_byte(array, *s); 109 ++s; 110 } 111 112 switch (seg_count) { 113 case 1: 114 if (!*s) { 115 build_append_byte(array, 0x0); /* NullName */ 116 } else { 117 build_append_nameseg(array, s); 118 } 119 break; 120 121 case 2: 122 build_append_byte(array, 0x2E); /* DualNamePrefix */ 123 build_append_nameseg(array, s); 124 build_append_nameseg(array, segs[1]); 125 break; 126 default: 127 build_append_byte(array, 0x2F); /* MultiNamePrefix */ 128 build_append_byte(array, seg_count); 129 130 /* handle the 1st segment manually due to prefix/root path */ 131 build_append_nameseg(array, s); 132 133 /* add the rest of segments */ 134 segs_iter = segs + 1; 135 while (*segs_iter) { 136 build_append_nameseg(array, *segs_iter); 137 ++segs_iter; 138 } 139 break; 140 } 141 g_strfreev(segs); 142 } 143 144 static void build_append_namestring(GArray *array, const char *format, ...) 145 { 146 va_list ap; 147 148 va_start(ap, format); 149 build_append_namestringv(array, format, ap); 150 va_end(ap); 151 } 152 153 /* 5.4 Definition Block Encoding */ 154 enum { 155 PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */ 156 PACKAGE_LENGTH_2BYTE_SHIFT = 4, 157 PACKAGE_LENGTH_3BYTE_SHIFT = 12, 158 PACKAGE_LENGTH_4BYTE_SHIFT = 20, 159 }; 160 161 static void 162 build_prepend_package_length(GArray *package, unsigned length, bool incl_self) 163 { 164 uint8_t byte; 165 unsigned length_bytes; 166 167 if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) { 168 length_bytes = 1; 169 } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) { 170 length_bytes = 2; 171 } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) { 172 length_bytes = 3; 173 } else { 174 length_bytes = 4; 175 } 176 177 /* 178 * NamedField uses PkgLength encoding but it doesn't include length 179 * of PkgLength itself. 180 */ 181 if (incl_self) { 182 /* 183 * PkgLength is the length of the inclusive length of the data 184 * and PkgLength's length itself when used for terms with 185 * explitit length. 186 */ 187 length += length_bytes; 188 } 189 190 switch (length_bytes) { 191 case 1: 192 byte = length; 193 build_prepend_byte(package, byte); 194 return; 195 case 4: 196 byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT; 197 build_prepend_byte(package, byte); 198 length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1; 199 /* fall through */ 200 case 3: 201 byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT; 202 build_prepend_byte(package, byte); 203 length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1; 204 /* fall through */ 205 case 2: 206 byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT; 207 build_prepend_byte(package, byte); 208 length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1; 209 /* fall through */ 210 } 211 /* 212 * Most significant two bits of byte zero indicate how many following bytes 213 * are in PkgLength encoding. 214 */ 215 byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length; 216 build_prepend_byte(package, byte); 217 } 218 219 static void 220 build_append_pkg_length(GArray *array, unsigned length, bool incl_self) 221 { 222 GArray *tmp = build_alloc_array(); 223 224 build_prepend_package_length(tmp, length, incl_self); 225 build_append_array(array, tmp); 226 build_free_array(tmp); 227 } 228 229 static void build_package(GArray *package, uint8_t op) 230 { 231 build_prepend_package_length(package, package->len, true); 232 build_prepend_byte(package, op); 233 } 234 235 static void build_extop_package(GArray *package, uint8_t op) 236 { 237 build_package(package, op); 238 build_prepend_byte(package, 0x5B); /* ExtOpPrefix */ 239 } 240 241 static void build_append_int_noprefix(GArray *table, uint64_t value, int size) 242 { 243 int i; 244 245 for (i = 0; i < size; ++i) { 246 build_append_byte(table, value & 0xFF); 247 value = value >> 8; 248 } 249 } 250 251 static void build_append_int(GArray *table, uint64_t value) 252 { 253 if (value == 0x00) { 254 build_append_byte(table, 0x00); /* ZeroOp */ 255 } else if (value == 0x01) { 256 build_append_byte(table, 0x01); /* OneOp */ 257 } else if (value <= 0xFF) { 258 build_append_byte(table, 0x0A); /* BytePrefix */ 259 build_append_int_noprefix(table, value, 1); 260 } else if (value <= 0xFFFF) { 261 build_append_byte(table, 0x0B); /* WordPrefix */ 262 build_append_int_noprefix(table, value, 2); 263 } else if (value <= 0xFFFFFFFF) { 264 build_append_byte(table, 0x0C); /* DWordPrefix */ 265 build_append_int_noprefix(table, value, 4); 266 } else { 267 build_append_byte(table, 0x0E); /* QWordPrefix */ 268 build_append_int_noprefix(table, value, 8); 269 } 270 } 271 272 static GPtrArray *alloc_list; 273 274 static Aml *aml_alloc(void) 275 { 276 Aml *var = g_new0(typeof(*var), 1); 277 278 g_ptr_array_add(alloc_list, var); 279 var->block_flags = AML_NO_OPCODE; 280 var->buf = build_alloc_array(); 281 return var; 282 } 283 284 static Aml *aml_opcode(uint8_t op) 285 { 286 Aml *var = aml_alloc(); 287 288 var->op = op; 289 var->block_flags = AML_OPCODE; 290 return var; 291 } 292 293 static Aml *aml_bundle(uint8_t op, AmlBlockFlags flags) 294 { 295 Aml *var = aml_alloc(); 296 297 var->op = op; 298 var->block_flags = flags; 299 return var; 300 } 301 302 static void aml_free(gpointer data, gpointer user_data) 303 { 304 Aml *var = data; 305 build_free_array(var->buf); 306 } 307 308 Aml *init_aml_allocator(void) 309 { 310 Aml *var; 311 312 assert(!alloc_list); 313 alloc_list = g_ptr_array_new(); 314 var = aml_alloc(); 315 return var; 316 } 317 318 void free_aml_allocator(void) 319 { 320 g_ptr_array_foreach(alloc_list, aml_free, NULL); 321 g_ptr_array_free(alloc_list, true); 322 alloc_list = 0; 323 } 324 325 /* pack data with DefBuffer encoding */ 326 static void build_buffer(GArray *array, uint8_t op) 327 { 328 GArray *data = build_alloc_array(); 329 330 build_append_int(data, array->len); 331 g_array_prepend_vals(array, data->data, data->len); 332 build_free_array(data); 333 build_package(array, op); 334 } 335 336 void aml_append(Aml *parent_ctx, Aml *child) 337 { 338 switch (child->block_flags) { 339 case AML_OPCODE: 340 build_append_byte(parent_ctx->buf, child->op); 341 break; 342 case AML_EXT_PACKAGE: 343 build_extop_package(child->buf, child->op); 344 break; 345 case AML_PACKAGE: 346 build_package(child->buf, child->op); 347 break; 348 case AML_RES_TEMPLATE: 349 build_append_byte(child->buf, 0x79); /* EndTag */ 350 /* 351 * checksum operations are treated as succeeded if checksum 352 * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag] 353 */ 354 build_append_byte(child->buf, 0); 355 /* fall through, to pack resources in buffer */ 356 case AML_BUFFER: 357 build_buffer(child->buf, child->op); 358 break; 359 case AML_NO_OPCODE: 360 break; 361 default: 362 assert(0); 363 break; 364 } 365 build_append_array(parent_ctx->buf, child->buf); 366 } 367 368 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefScope */ 369 Aml *aml_scope(const char *name_format, ...) 370 { 371 va_list ap; 372 Aml *var = aml_bundle(0x10 /* ScopeOp */, AML_PACKAGE); 373 va_start(ap, name_format); 374 build_append_namestringv(var->buf, name_format, ap); 375 va_end(ap); 376 return var; 377 } 378 379 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */ 380 Aml *aml_return(Aml *val) 381 { 382 Aml *var = aml_opcode(0xA4 /* ReturnOp */); 383 aml_append(var, val); 384 return var; 385 } 386 387 /* 388 * ACPI 1.0b: 16.2.3 Data Objects Encoding: 389 * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp 390 */ 391 Aml *aml_int(const uint64_t val) 392 { 393 Aml *var = aml_alloc(); 394 build_append_int(var->buf, val); 395 return var; 396 } 397 398 /* 399 * helper to construct NameString, which returns Aml object 400 * for using with aml_append or other aml_* terms 401 */ 402 Aml *aml_name(const char *name_format, ...) 403 { 404 va_list ap; 405 Aml *var = aml_alloc(); 406 va_start(ap, name_format); 407 build_append_namestringv(var->buf, name_format, ap); 408 va_end(ap); 409 return var; 410 } 411 412 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */ 413 Aml *aml_name_decl(const char *name, Aml *val) 414 { 415 Aml *var = aml_opcode(0x08 /* NameOp */); 416 build_append_namestring(var->buf, "%s", name); 417 aml_append(var, val); 418 return var; 419 } 420 421 /* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */ 422 Aml *aml_arg(int pos) 423 { 424 Aml *var; 425 uint8_t op = 0x68 /* ARG0 op */ + pos; 426 427 assert(pos <= 6); 428 var = aml_opcode(op); 429 return var; 430 } 431 432 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */ 433 Aml *aml_store(Aml *val, Aml *target) 434 { 435 Aml *var = aml_opcode(0x70 /* StoreOp */); 436 aml_append(var, val); 437 aml_append(var, target); 438 return var; 439 } 440 441 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */ 442 Aml *aml_and(Aml *arg1, Aml *arg2) 443 { 444 Aml *var = aml_opcode(0x7B /* AndOp */); 445 aml_append(var, arg1); 446 aml_append(var, arg2); 447 build_append_int(var->buf, 0x00 /* NullNameOp */); 448 return var; 449 } 450 451 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */ 452 Aml *aml_notify(Aml *arg1, Aml *arg2) 453 { 454 Aml *var = aml_opcode(0x86 /* NotifyOp */); 455 aml_append(var, arg1); 456 aml_append(var, arg2); 457 return var; 458 } 459 460 /* helper to call method with 1 argument */ 461 Aml *aml_call1(const char *method, Aml *arg1) 462 { 463 Aml *var = aml_alloc(); 464 build_append_namestring(var->buf, "%s", method); 465 aml_append(var, arg1); 466 return var; 467 } 468 469 /* helper to call method with 2 arguments */ 470 Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2) 471 { 472 Aml *var = aml_alloc(); 473 build_append_namestring(var->buf, "%s", method); 474 aml_append(var, arg1); 475 aml_append(var, arg2); 476 return var; 477 } 478 479 /* helper to call method with 3 arguments */ 480 Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3) 481 { 482 Aml *var = aml_alloc(); 483 build_append_namestring(var->buf, "%s", method); 484 aml_append(var, arg1); 485 aml_append(var, arg2); 486 aml_append(var, arg3); 487 return var; 488 } 489 490 /* helper to call method with 4 arguments */ 491 Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4) 492 { 493 Aml *var = aml_alloc(); 494 build_append_namestring(var->buf, "%s", method); 495 aml_append(var, arg1); 496 aml_append(var, arg2); 497 aml_append(var, arg3); 498 aml_append(var, arg4); 499 return var; 500 } 501 502 /* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */ 503 Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, 504 uint8_t aln, uint8_t len) 505 { 506 Aml *var = aml_alloc(); 507 build_append_byte(var->buf, 0x47); /* IO port descriptor */ 508 build_append_byte(var->buf, dec); 509 build_append_byte(var->buf, min_base & 0xff); 510 build_append_byte(var->buf, (min_base >> 8) & 0xff); 511 build_append_byte(var->buf, max_base & 0xff); 512 build_append_byte(var->buf, (max_base >> 8) & 0xff); 513 build_append_byte(var->buf, aln); 514 build_append_byte(var->buf, len); 515 return var; 516 } 517 518 /* 519 * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor 520 * 521 * More verbose description at: 522 * ACPI 5.0: 19.5.64 IRQNoFlags (Interrupt Resource Descriptor Macro) 523 * 6.4.2.1 IRQ Descriptor 524 */ 525 Aml *aml_irq_no_flags(uint8_t irq) 526 { 527 uint16_t irq_mask; 528 Aml *var = aml_alloc(); 529 530 assert(irq < 16); 531 build_append_byte(var->buf, 0x22); /* IRQ descriptor 2 byte form */ 532 533 irq_mask = 1U << irq; 534 build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */ 535 build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */ 536 return var; 537 } 538 539 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */ 540 Aml *aml_equal(Aml *arg1, Aml *arg2) 541 { 542 Aml *var = aml_opcode(0x93 /* LequalOp */); 543 aml_append(var, arg1); 544 aml_append(var, arg2); 545 build_append_int(var->buf, 0x00); /* NullNameOp */ 546 return var; 547 } 548 549 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefIfElse */ 550 Aml *aml_if(Aml *predicate) 551 { 552 Aml *var = aml_bundle(0xA0 /* IfOp */, AML_PACKAGE); 553 aml_append(var, predicate); 554 return var; 555 } 556 557 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */ 558 Aml *aml_method(const char *name, int arg_count) 559 { 560 Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE); 561 build_append_namestring(var->buf, "%s", name); 562 build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */ 563 return var; 564 } 565 566 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */ 567 Aml *aml_device(const char *name_format, ...) 568 { 569 va_list ap; 570 Aml *var = aml_bundle(0x82 /* DeviceOp */, AML_EXT_PACKAGE); 571 va_start(ap, name_format); 572 build_append_namestringv(var->buf, name_format, ap); 573 va_end(ap); 574 return var; 575 } 576 577 /* ACPI 1.0b: 6.4.1 ASL Macros for Resource Descriptors */ 578 Aml *aml_resource_template(void) 579 { 580 /* ResourceTemplate is a buffer of Resources with EndTag at the end */ 581 Aml *var = aml_bundle(0x11 /* BufferOp */, AML_RES_TEMPLATE); 582 return var; 583 } 584 585 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer */ 586 Aml *aml_buffer(void) 587 { 588 Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER); 589 return var; 590 } 591 592 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefPackage */ 593 Aml *aml_package(uint8_t num_elements) 594 { 595 Aml *var = aml_bundle(0x12 /* PackageOp */, AML_PACKAGE); 596 build_append_byte(var->buf, num_elements); 597 return var; 598 } 599 600 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */ 601 Aml *aml_operation_region(const char *name, AmlRegionSpace rs, 602 uint32_t offset, uint32_t len) 603 { 604 Aml *var = aml_alloc(); 605 build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ 606 build_append_byte(var->buf, 0x80); /* OpRegionOp */ 607 build_append_namestring(var->buf, "%s", name); 608 build_append_byte(var->buf, rs); 609 build_append_int(var->buf, offset); 610 build_append_int(var->buf, len); 611 return var; 612 } 613 614 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */ 615 Aml *aml_named_field(const char *name, unsigned length) 616 { 617 Aml *var = aml_alloc(); 618 build_append_nameseg(var->buf, name); 619 build_append_pkg_length(var->buf, length, false); 620 return var; 621 } 622 623 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */ 624 Aml *aml_reserved_field(unsigned length) 625 { 626 Aml *var = aml_alloc(); 627 /* ReservedField := 0x00 PkgLength */ 628 build_append_byte(var->buf, 0x00); 629 build_append_pkg_length(var->buf, length, false); 630 return var; 631 } 632 633 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */ 634 Aml *aml_field(const char *name, AmlFieldFlags flags) 635 { 636 Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE); 637 build_append_namestring(var->buf, "%s", name); 638 build_append_byte(var->buf, flags); 639 return var; 640 } 641 642 /* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */ 643 Aml *aml_string(const char *name_format, ...) 644 { 645 Aml *var = aml_opcode(0x0D /* StringPrefix */); 646 va_list ap, va_len; 647 char *s; 648 int len; 649 650 va_start(ap, name_format); 651 va_copy(va_len, ap); 652 len = vsnprintf(NULL, 0, name_format, va_len); 653 va_end(va_len); 654 len += 1; 655 s = g_new0(typeof(*s), len); 656 657 len = vsnprintf(s, len, name_format, ap); 658 va_end(ap); 659 660 g_array_append_vals(var->buf, s, len); 661 build_append_byte(var->buf, 0x0); /* NullChar */ 662 g_free(s); 663 664 return var; 665 } 666 667 /* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */ 668 Aml *aml_local(int num) 669 { 670 Aml *var; 671 uint8_t op = 0x60 /* Local0Op */ + num; 672 673 assert(num <= 7); 674 var = aml_opcode(op); 675 return var; 676 } 677 678 /* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */ 679 Aml *aml_varpackage(uint32_t num_elements) 680 { 681 Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE); 682 build_append_int(var->buf, num_elements); 683 return var; 684 } 685 686 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */ 687 Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, 688 const char *name_format, ...) 689 { 690 va_list ap; 691 Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE); 692 va_start(ap, name_format); 693 build_append_namestringv(var->buf, name_format, ap); 694 va_end(ap); 695 build_append_byte(var->buf, proc_id); /* ProcID */ 696 build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr)); 697 build_append_byte(var->buf, pblk_len); /* PblkLen */ 698 return var; 699 } 700 701 static uint8_t Hex2Digit(char c) 702 { 703 if (c >= 'A') { 704 return c - 'A' + 10; 705 } 706 707 return c - '0'; 708 } 709 710 /* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */ 711 Aml *aml_eisaid(const char *str) 712 { 713 Aml *var = aml_alloc(); 714 uint32_t id; 715 716 g_assert(strlen(str) == 7); 717 id = (str[0] - 0x40) << 26 | 718 (str[1] - 0x40) << 21 | 719 (str[2] - 0x40) << 16 | 720 Hex2Digit(str[3]) << 12 | 721 Hex2Digit(str[4]) << 8 | 722 Hex2Digit(str[5]) << 4 | 723 Hex2Digit(str[6]); 724 725 build_append_byte(var->buf, 0x0C); /* DWordPrefix */ 726 build_append_int_noprefix(var->buf, bswap32(id), sizeof(id)); 727 return var; 728 } 729 730 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */ 731 static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed, 732 AmlMaxFixed max_fixed, AmlDecode dec, 733 uint8_t type_flags) 734 { 735 uint8_t flags = max_fixed | min_fixed | dec; 736 Aml *var = aml_alloc(); 737 738 build_append_byte(var->buf, type); 739 build_append_byte(var->buf, flags); 740 build_append_byte(var->buf, type_flags); /* Type Specific Flags */ 741 return var; 742 } 743 744 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */ 745 static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 746 AmlMaxFixed max_fixed, AmlDecode dec, 747 uint16_t addr_gran, uint16_t addr_min, 748 uint16_t addr_max, uint16_t addr_trans, 749 uint16_t len, uint8_t type_flags) 750 { 751 Aml *var = aml_alloc(); 752 753 build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */ 754 /* minimum length since we do not encode optional fields */ 755 build_append_byte(var->buf, 0x0D); 756 build_append_byte(var->buf, 0x0); 757 758 aml_append(var, 759 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 760 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 761 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 762 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 763 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 764 build_append_int_noprefix(var->buf, len, sizeof(len)); 765 return var; 766 } 767 768 /* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */ 769 static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 770 AmlMaxFixed max_fixed, AmlDecode dec, 771 uint32_t addr_gran, uint32_t addr_min, 772 uint32_t addr_max, uint32_t addr_trans, 773 uint32_t len, uint8_t type_flags) 774 { 775 Aml *var = aml_alloc(); 776 777 build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */ 778 /* minimum length since we do not encode optional fields */ 779 build_append_byte(var->buf, 23); 780 build_append_byte(var->buf, 0x0); 781 782 783 aml_append(var, 784 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 785 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 786 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 787 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 788 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 789 build_append_int_noprefix(var->buf, len, sizeof(len)); 790 return var; 791 } 792 793 /* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */ 794 static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 795 AmlMaxFixed max_fixed, AmlDecode dec, 796 uint64_t addr_gran, uint64_t addr_min, 797 uint64_t addr_max, uint64_t addr_trans, 798 uint64_t len, uint8_t type_flags) 799 { 800 Aml *var = aml_alloc(); 801 802 build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */ 803 /* minimum length since we do not encode optional fields */ 804 build_append_byte(var->buf, 0x2B); 805 build_append_byte(var->buf, 0x0); 806 807 aml_append(var, 808 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 809 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 810 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 811 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 812 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 813 build_append_int_noprefix(var->buf, len, sizeof(len)); 814 return var; 815 } 816 817 /* 818 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor 819 * 820 * More verbose description at: 821 * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro) 822 */ 823 Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, 824 AmlDecode dec, uint16_t addr_gran, 825 uint16_t addr_min, uint16_t addr_max, 826 uint16_t addr_trans, uint16_t len) 827 828 { 829 return aml_word_as_desc(aml_bus_number_range, min_fixed, max_fixed, dec, 830 addr_gran, addr_min, addr_max, addr_trans, len, 0); 831 } 832 833 /* 834 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor 835 * 836 * More verbose description at: 837 * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro) 838 */ 839 Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, 840 AmlDecode dec, AmlISARanges isa_ranges, 841 uint16_t addr_gran, uint16_t addr_min, 842 uint16_t addr_max, uint16_t addr_trans, 843 uint16_t len) 844 845 { 846 return aml_word_as_desc(aml_io_range, min_fixed, max_fixed, dec, 847 addr_gran, addr_min, addr_max, addr_trans, len, 848 isa_ranges); 849 } 850 851 /* 852 * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor 853 * 854 * More verbose description at: 855 * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro) 856 */ 857 Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, 858 AmlMaxFixed max_fixed, AmlCacheble cacheable, 859 AmlReadAndWrite read_and_write, 860 uint32_t addr_gran, uint32_t addr_min, 861 uint32_t addr_max, uint32_t addr_trans, 862 uint32_t len) 863 { 864 uint8_t flags = read_and_write | (cacheable << 1); 865 866 return aml_dword_as_desc(aml_memory_range, min_fixed, max_fixed, 867 dec, addr_gran, addr_min, addr_max, 868 addr_trans, len, flags); 869 } 870 871 /* 872 * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor 873 * 874 * More verbose description at: 875 * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro) 876 */ 877 Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, 878 AmlMaxFixed max_fixed, AmlCacheble cacheable, 879 AmlReadAndWrite read_and_write, 880 uint64_t addr_gran, uint64_t addr_min, 881 uint64_t addr_max, uint64_t addr_trans, 882 uint64_t len) 883 { 884 uint8_t flags = read_and_write | (cacheable << 1); 885 886 return aml_qword_as_desc(aml_memory_range, min_fixed, max_fixed, 887 dec, addr_gran, addr_min, addr_max, 888 addr_trans, len, flags); 889 } 890