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