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