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 GArray *build_alloc_array(void) 31 { 32 return g_array_new(false, true /* clear */, 1); 33 } 34 35 void build_free_array(GArray *array) 36 { 37 g_array_free(array, true); 38 } 39 40 void build_prepend_byte(GArray *array, uint8_t val) 41 { 42 g_array_prepend_val(array, val); 43 } 44 45 void build_append_byte(GArray *array, uint8_t val) 46 { 47 g_array_append_val(array, val); 48 } 49 50 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 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 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 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 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 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) 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_with_free_func(aml_free); 314 var = aml_alloc(); 315 return var; 316 } 317 318 void free_aml_allocator(void) 319 { 320 g_ptr_array_free(alloc_list, true); 321 alloc_list = 0; 322 } 323 324 /* pack data with DefBuffer encoding */ 325 static void build_buffer(GArray *array, uint8_t op) 326 { 327 GArray *data = build_alloc_array(); 328 329 build_append_int(data, array->len); 330 g_array_prepend_vals(array, data->data, data->len); 331 build_free_array(data); 332 build_package(array, op); 333 } 334 335 void aml_append(Aml *parent_ctx, Aml *child) 336 { 337 switch (child->block_flags) { 338 case AML_OPCODE: 339 build_append_byte(parent_ctx->buf, child->op); 340 break; 341 case AML_EXT_PACKAGE: 342 build_extop_package(child->buf, child->op); 343 break; 344 case AML_PACKAGE: 345 build_package(child->buf, child->op); 346 break; 347 case AML_RES_TEMPLATE: 348 build_append_byte(child->buf, 0x79); /* EndTag */ 349 /* 350 * checksum operations are treated as succeeded if checksum 351 * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag] 352 */ 353 build_append_byte(child->buf, 0); 354 /* fall through, to pack resources in buffer */ 355 case AML_BUFFER: 356 build_buffer(child->buf, child->op); 357 break; 358 case AML_NO_OPCODE: 359 break; 360 default: 361 assert(0); 362 break; 363 } 364 build_append_array(parent_ctx->buf, child->buf); 365 } 366 367 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefScope */ 368 Aml *aml_scope(const char *name_format, ...) 369 { 370 va_list ap; 371 Aml *var = aml_bundle(0x10 /* ScopeOp */, AML_PACKAGE); 372 va_start(ap, name_format); 373 build_append_namestringv(var->buf, name_format, ap); 374 va_end(ap); 375 return var; 376 } 377 378 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */ 379 Aml *aml_return(Aml *val) 380 { 381 Aml *var = aml_opcode(0xA4 /* ReturnOp */); 382 aml_append(var, val); 383 return var; 384 } 385 386 /* 387 * ACPI 1.0b: 16.2.3 Data Objects Encoding: 388 * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp 389 */ 390 Aml *aml_int(const uint64_t val) 391 { 392 Aml *var = aml_alloc(); 393 build_append_int(var->buf, val); 394 return var; 395 } 396 397 /* 398 * helper to construct NameString, which returns Aml object 399 * for using with aml_append or other aml_* terms 400 */ 401 Aml *aml_name(const char *name_format, ...) 402 { 403 va_list ap; 404 Aml *var = aml_alloc(); 405 va_start(ap, name_format); 406 build_append_namestringv(var->buf, name_format, ap); 407 va_end(ap); 408 return var; 409 } 410 411 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */ 412 Aml *aml_name_decl(const char *name, Aml *val) 413 { 414 Aml *var = aml_opcode(0x08 /* NameOp */); 415 build_append_namestring(var->buf, "%s", name); 416 aml_append(var, val); 417 return var; 418 } 419 420 /* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */ 421 Aml *aml_arg(int pos) 422 { 423 Aml *var; 424 uint8_t op = 0x68 /* ARG0 op */ + pos; 425 426 assert(pos <= 6); 427 var = aml_opcode(op); 428 return var; 429 } 430 431 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */ 432 Aml *aml_store(Aml *val, Aml *target) 433 { 434 Aml *var = aml_opcode(0x70 /* StoreOp */); 435 aml_append(var, val); 436 aml_append(var, target); 437 return var; 438 } 439 440 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */ 441 Aml *aml_and(Aml *arg1, Aml *arg2) 442 { 443 Aml *var = aml_opcode(0x7B /* AndOp */); 444 aml_append(var, arg1); 445 aml_append(var, arg2); 446 build_append_int(var->buf, 0x00 /* NullNameOp */); 447 return var; 448 } 449 450 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */ 451 Aml *aml_notify(Aml *arg1, Aml *arg2) 452 { 453 Aml *var = aml_opcode(0x86 /* NotifyOp */); 454 aml_append(var, arg1); 455 aml_append(var, arg2); 456 return var; 457 } 458 459 /* helper to call method with 1 argument */ 460 Aml *aml_call1(const char *method, Aml *arg1) 461 { 462 Aml *var = aml_alloc(); 463 build_append_namestring(var->buf, "%s", method); 464 aml_append(var, arg1); 465 return var; 466 } 467 468 /* helper to call method with 2 arguments */ 469 Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2) 470 { 471 Aml *var = aml_alloc(); 472 build_append_namestring(var->buf, "%s", method); 473 aml_append(var, arg1); 474 aml_append(var, arg2); 475 return var; 476 } 477 478 /* helper to call method with 3 arguments */ 479 Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3) 480 { 481 Aml *var = aml_alloc(); 482 build_append_namestring(var->buf, "%s", method); 483 aml_append(var, arg1); 484 aml_append(var, arg2); 485 aml_append(var, arg3); 486 return var; 487 } 488 489 /* helper to call method with 4 arguments */ 490 Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4) 491 { 492 Aml *var = aml_alloc(); 493 build_append_namestring(var->buf, "%s", method); 494 aml_append(var, arg1); 495 aml_append(var, arg2); 496 aml_append(var, arg3); 497 aml_append(var, arg4); 498 return var; 499 } 500 501 /* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */ 502 Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, 503 uint8_t aln, uint8_t len) 504 { 505 Aml *var = aml_alloc(); 506 build_append_byte(var->buf, 0x47); /* IO port descriptor */ 507 build_append_byte(var->buf, dec); 508 build_append_byte(var->buf, min_base & 0xff); 509 build_append_byte(var->buf, (min_base >> 8) & 0xff); 510 build_append_byte(var->buf, max_base & 0xff); 511 build_append_byte(var->buf, (max_base >> 8) & 0xff); 512 build_append_byte(var->buf, aln); 513 build_append_byte(var->buf, len); 514 return var; 515 } 516 517 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */ 518 Aml *aml_equal(Aml *arg1, Aml *arg2) 519 { 520 Aml *var = aml_opcode(0x93 /* LequalOp */); 521 aml_append(var, arg1); 522 aml_append(var, arg2); 523 build_append_int(var->buf, 0x00); /* NullNameOp */ 524 return var; 525 } 526 527 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefIfElse */ 528 Aml *aml_if(Aml *predicate) 529 { 530 Aml *var = aml_bundle(0xA0 /* IfOp */, AML_PACKAGE); 531 aml_append(var, predicate); 532 return var; 533 } 534 535 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */ 536 Aml *aml_method(const char *name, int arg_count) 537 { 538 Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE); 539 build_append_namestring(var->buf, "%s", name); 540 build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */ 541 return var; 542 } 543 544 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */ 545 Aml *aml_device(const char *name_format, ...) 546 { 547 va_list ap; 548 Aml *var = aml_bundle(0x82 /* DeviceOp */, AML_EXT_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: 6.4.1 ASL Macros for Resource Descriptors */ 556 Aml *aml_resource_template(void) 557 { 558 /* ResourceTemplate is a buffer of Resources with EndTag at the end */ 559 Aml *var = aml_bundle(0x11 /* BufferOp */, AML_RES_TEMPLATE); 560 return var; 561 } 562 563 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer */ 564 Aml *aml_buffer(void) 565 { 566 Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER); 567 return var; 568 } 569 570 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefPackage */ 571 Aml *aml_package(uint8_t num_elements) 572 { 573 Aml *var = aml_bundle(0x12 /* PackageOp */, AML_PACKAGE); 574 build_append_byte(var->buf, num_elements); 575 return var; 576 } 577 578 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */ 579 Aml *aml_operation_region(const char *name, AmlRegionSpace rs, 580 uint32_t offset, uint32_t len) 581 { 582 Aml *var = aml_alloc(); 583 build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ 584 build_append_byte(var->buf, 0x80); /* OpRegionOp */ 585 build_append_namestring(var->buf, "%s", name); 586 build_append_byte(var->buf, rs); 587 build_append_int(var->buf, offset); 588 build_append_int(var->buf, len); 589 return var; 590 } 591 592 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */ 593 Aml *aml_named_field(const char *name, unsigned length) 594 { 595 Aml *var = aml_alloc(); 596 build_append_nameseg(var->buf, name); 597 build_append_pkg_length(var->buf, length, false); 598 return var; 599 } 600 601 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */ 602 Aml *aml_reserved_field(unsigned length) 603 { 604 Aml *var = aml_alloc(); 605 /* ReservedField := 0x00 PkgLength */ 606 build_append_byte(var->buf, 0x00); 607 build_append_pkg_length(var->buf, length, false); 608 return var; 609 } 610 611 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */ 612 Aml *aml_field(const char *name, AmlFieldFlags flags) 613 { 614 Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE); 615 build_append_namestring(var->buf, "%s", name); 616 build_append_byte(var->buf, flags); 617 return var; 618 } 619 620 /* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */ 621 Aml *aml_string(const char *name_format, ...) 622 { 623 Aml *var = aml_opcode(0x0D /* StringPrefix */); 624 va_list ap, va_len; 625 char *s; 626 int len; 627 628 va_start(ap, name_format); 629 va_copy(va_len, ap); 630 len = vsnprintf(NULL, 0, name_format, va_len); 631 va_end(va_len); 632 len += 1; 633 s = g_new0(typeof(*s), len); 634 635 len = vsnprintf(s, len, name_format, ap); 636 va_end(ap); 637 638 g_array_append_vals(var->buf, s, len); 639 build_append_byte(var->buf, 0x0); /* NullChar */ 640 g_free(s); 641 642 return var; 643 } 644 645 /* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */ 646 Aml *aml_local(int num) 647 { 648 Aml *var; 649 uint8_t op = 0x60 /* Local0Op */ + num; 650 651 assert(num <= 7); 652 var = aml_opcode(op); 653 return var; 654 } 655 656 /* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */ 657 Aml *aml_varpackage(uint32_t num_elements) 658 { 659 Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE); 660 build_append_int(var->buf, num_elements); 661 return var; 662 } 663 664 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */ 665 Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, 666 const char *name_format, ...) 667 { 668 va_list ap; 669 Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE); 670 va_start(ap, name_format); 671 build_append_namestringv(var->buf, name_format, ap); 672 va_end(ap); 673 build_append_byte(var->buf, proc_id); /* ProcID */ 674 build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr)); 675 build_append_byte(var->buf, pblk_len); /* PblkLen */ 676 return var; 677 } 678 679 static uint8_t Hex2Digit(char c) 680 { 681 if (c >= 'A') { 682 return c - 'A' + 10; 683 } 684 685 return c - '0'; 686 } 687 688 /* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */ 689 Aml *aml_eisaid(const char *str) 690 { 691 Aml *var = aml_alloc(); 692 uint32_t id; 693 694 g_assert(strlen(str) == 7); 695 id = (str[0] - 0x40) << 26 | 696 (str[1] - 0x40) << 21 | 697 (str[2] - 0x40) << 16 | 698 Hex2Digit(str[3]) << 12 | 699 Hex2Digit(str[4]) << 8 | 700 Hex2Digit(str[5]) << 4 | 701 Hex2Digit(str[6]); 702 703 build_append_byte(var->buf, 0x0C); /* DWordPrefix */ 704 build_append_int_noprefix(var->buf, bswap32(id), sizeof(id)); 705 return var; 706 } 707 708 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */ 709 static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed, 710 AmlMaxFixed max_fixed, AmlDecode dec, 711 uint8_t type_flags) 712 { 713 uint8_t flags = max_fixed | min_fixed | dec; 714 Aml *var = aml_alloc(); 715 716 build_append_byte(var->buf, type); 717 build_append_byte(var->buf, flags); 718 build_append_byte(var->buf, type_flags); /* Type Specific Flags */ 719 return var; 720 } 721 722 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */ 723 static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 724 AmlMaxFixed max_fixed, AmlDecode dec, 725 uint16_t addr_gran, uint16_t addr_min, 726 uint16_t addr_max, uint16_t addr_trans, 727 uint16_t len, uint8_t type_flags) 728 { 729 Aml *var = aml_alloc(); 730 731 build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */ 732 /* minimum length since we do not encode optional fields */ 733 build_append_byte(var->buf, 0x0D); 734 build_append_byte(var->buf, 0x0); 735 736 aml_append(var, 737 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 738 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 739 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 740 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 741 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 742 build_append_int_noprefix(var->buf, len, sizeof(len)); 743 return var; 744 } 745 746 /* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */ 747 static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 748 AmlMaxFixed max_fixed, AmlDecode dec, 749 uint32_t addr_gran, uint32_t addr_min, 750 uint32_t addr_max, uint32_t addr_trans, 751 uint32_t len, uint8_t type_flags) 752 { 753 Aml *var = aml_alloc(); 754 755 build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */ 756 /* minimum length since we do not encode optional fields */ 757 build_append_byte(var->buf, 23); 758 build_append_byte(var->buf, 0x0); 759 760 761 aml_append(var, 762 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 763 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 764 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 765 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 766 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 767 build_append_int_noprefix(var->buf, len, sizeof(len)); 768 return var; 769 } 770 771 /* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */ 772 static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 773 AmlMaxFixed max_fixed, AmlDecode dec, 774 uint64_t addr_gran, uint64_t addr_min, 775 uint64_t addr_max, uint64_t addr_trans, 776 uint64_t len, uint8_t type_flags) 777 { 778 Aml *var = aml_alloc(); 779 780 build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */ 781 /* minimum length since we do not encode optional fields */ 782 build_append_byte(var->buf, 0x2B); 783 build_append_byte(var->buf, 0x0); 784 785 aml_append(var, 786 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 787 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 788 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 789 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 790 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 791 build_append_int_noprefix(var->buf, len, sizeof(len)); 792 return var; 793 } 794 795 /* 796 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor 797 * 798 * More verbose description at: 799 * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro) 800 */ 801 Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, 802 AmlDecode dec, uint16_t addr_gran, 803 uint16_t addr_min, uint16_t addr_max, 804 uint16_t addr_trans, uint16_t len) 805 806 { 807 return aml_word_as_desc(aml_bus_number_range, min_fixed, max_fixed, dec, 808 addr_gran, addr_min, addr_max, addr_trans, len, 0); 809 } 810 811 /* 812 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor 813 * 814 * More verbose description at: 815 * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro) 816 */ 817 Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, 818 AmlDecode dec, AmlISARanges isa_ranges, 819 uint16_t addr_gran, uint16_t addr_min, 820 uint16_t addr_max, uint16_t addr_trans, 821 uint16_t len) 822 823 { 824 return aml_word_as_desc(aml_io_range, min_fixed, max_fixed, dec, 825 addr_gran, addr_min, addr_max, addr_trans, len, 826 isa_ranges); 827 } 828 829 /* 830 * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor 831 * 832 * More verbose description at: 833 * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro) 834 */ 835 Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, 836 AmlMaxFixed max_fixed, AmlCacheble cacheable, 837 AmlReadAndWrite read_and_write, 838 uint32_t addr_gran, uint32_t addr_min, 839 uint32_t addr_max, uint32_t addr_trans, 840 uint32_t len) 841 { 842 uint8_t flags = read_and_write | (cacheable << 1); 843 844 return aml_dword_as_desc(aml_memory_range, min_fixed, max_fixed, 845 dec, addr_gran, addr_min, addr_max, 846 addr_trans, len, flags); 847 } 848 849 /* 850 * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor 851 * 852 * More verbose description at: 853 * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro) 854 */ 855 Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, 856 AmlMaxFixed max_fixed, AmlCacheble cacheable, 857 AmlReadAndWrite read_and_write, 858 uint64_t addr_gran, uint64_t addr_min, 859 uint64_t addr_max, uint64_t addr_trans, 860 uint64_t len) 861 { 862 uint8_t flags = read_and_write | (cacheable << 1); 863 864 return aml_qword_as_desc(aml_memory_range, min_fixed, max_fixed, 865 dec, addr_gran, addr_min, addr_max, 866 addr_trans, len, flags); 867 } 868