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, AmlAccessType type, AmlUpdateRule rule) 640 { 641 Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE); 642 uint8_t flags = rule << 5 | type; 643 644 build_append_namestring(var->buf, "%s", name); 645 build_append_byte(var->buf, flags); 646 return var; 647 } 648 649 /* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */ 650 Aml *aml_string(const char *name_format, ...) 651 { 652 Aml *var = aml_opcode(0x0D /* StringPrefix */); 653 va_list ap, va_len; 654 char *s; 655 int len; 656 657 va_start(ap, name_format); 658 va_copy(va_len, ap); 659 len = vsnprintf(NULL, 0, name_format, va_len); 660 va_end(va_len); 661 len += 1; 662 s = g_new0(typeof(*s), len); 663 664 len = vsnprintf(s, len, name_format, ap); 665 va_end(ap); 666 667 g_array_append_vals(var->buf, s, len); 668 build_append_byte(var->buf, 0x0); /* NullChar */ 669 g_free(s); 670 671 return var; 672 } 673 674 /* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */ 675 Aml *aml_local(int num) 676 { 677 Aml *var; 678 uint8_t op = 0x60 /* Local0Op */ + num; 679 680 assert(num <= 7); 681 var = aml_opcode(op); 682 return var; 683 } 684 685 /* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */ 686 Aml *aml_varpackage(uint32_t num_elements) 687 { 688 Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE); 689 build_append_int(var->buf, num_elements); 690 return var; 691 } 692 693 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */ 694 Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, 695 const char *name_format, ...) 696 { 697 va_list ap; 698 Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE); 699 va_start(ap, name_format); 700 build_append_namestringv(var->buf, name_format, ap); 701 va_end(ap); 702 build_append_byte(var->buf, proc_id); /* ProcID */ 703 build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr)); 704 build_append_byte(var->buf, pblk_len); /* PblkLen */ 705 return var; 706 } 707 708 static uint8_t Hex2Digit(char c) 709 { 710 if (c >= 'A') { 711 return c - 'A' + 10; 712 } 713 714 return c - '0'; 715 } 716 717 /* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */ 718 Aml *aml_eisaid(const char *str) 719 { 720 Aml *var = aml_alloc(); 721 uint32_t id; 722 723 g_assert(strlen(str) == 7); 724 id = (str[0] - 0x40) << 26 | 725 (str[1] - 0x40) << 21 | 726 (str[2] - 0x40) << 16 | 727 Hex2Digit(str[3]) << 12 | 728 Hex2Digit(str[4]) << 8 | 729 Hex2Digit(str[5]) << 4 | 730 Hex2Digit(str[6]); 731 732 build_append_byte(var->buf, 0x0C); /* DWordPrefix */ 733 build_append_int_noprefix(var->buf, bswap32(id), sizeof(id)); 734 return var; 735 } 736 737 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */ 738 static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed, 739 AmlMaxFixed max_fixed, AmlDecode dec, 740 uint8_t type_flags) 741 { 742 uint8_t flags = max_fixed | min_fixed | dec; 743 Aml *var = aml_alloc(); 744 745 build_append_byte(var->buf, type); 746 build_append_byte(var->buf, flags); 747 build_append_byte(var->buf, type_flags); /* Type Specific Flags */ 748 return var; 749 } 750 751 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */ 752 static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 753 AmlMaxFixed max_fixed, AmlDecode dec, 754 uint16_t addr_gran, uint16_t addr_min, 755 uint16_t addr_max, uint16_t addr_trans, 756 uint16_t len, uint8_t type_flags) 757 { 758 Aml *var = aml_alloc(); 759 760 build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */ 761 /* minimum length since we do not encode optional fields */ 762 build_append_byte(var->buf, 0x0D); 763 build_append_byte(var->buf, 0x0); 764 765 aml_append(var, 766 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 767 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 768 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 769 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 770 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 771 build_append_int_noprefix(var->buf, len, sizeof(len)); 772 return var; 773 } 774 775 /* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */ 776 static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 777 AmlMaxFixed max_fixed, AmlDecode dec, 778 uint32_t addr_gran, uint32_t addr_min, 779 uint32_t addr_max, uint32_t addr_trans, 780 uint32_t len, uint8_t type_flags) 781 { 782 Aml *var = aml_alloc(); 783 784 build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */ 785 /* minimum length since we do not encode optional fields */ 786 build_append_byte(var->buf, 23); 787 build_append_byte(var->buf, 0x0); 788 789 790 aml_append(var, 791 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 792 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 793 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 794 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 795 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 796 build_append_int_noprefix(var->buf, len, sizeof(len)); 797 return var; 798 } 799 800 /* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */ 801 static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, 802 AmlMaxFixed max_fixed, AmlDecode dec, 803 uint64_t addr_gran, uint64_t addr_min, 804 uint64_t addr_max, uint64_t addr_trans, 805 uint64_t len, uint8_t type_flags) 806 { 807 Aml *var = aml_alloc(); 808 809 build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */ 810 /* minimum length since we do not encode optional fields */ 811 build_append_byte(var->buf, 0x2B); 812 build_append_byte(var->buf, 0x0); 813 814 aml_append(var, 815 aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); 816 build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); 817 build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); 818 build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); 819 build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); 820 build_append_int_noprefix(var->buf, len, sizeof(len)); 821 return var; 822 } 823 824 /* 825 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor 826 * 827 * More verbose description at: 828 * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro) 829 */ 830 Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, 831 AmlDecode dec, uint16_t addr_gran, 832 uint16_t addr_min, uint16_t addr_max, 833 uint16_t addr_trans, uint16_t len) 834 835 { 836 return aml_word_as_desc(aml_bus_number_range, min_fixed, max_fixed, dec, 837 addr_gran, addr_min, addr_max, addr_trans, len, 0); 838 } 839 840 /* 841 * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor 842 * 843 * More verbose description at: 844 * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro) 845 */ 846 Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, 847 AmlDecode dec, AmlISARanges isa_ranges, 848 uint16_t addr_gran, uint16_t addr_min, 849 uint16_t addr_max, uint16_t addr_trans, 850 uint16_t len) 851 852 { 853 return aml_word_as_desc(aml_io_range, min_fixed, max_fixed, dec, 854 addr_gran, addr_min, addr_max, addr_trans, len, 855 isa_ranges); 856 } 857 858 /* 859 * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor 860 * 861 * More verbose description at: 862 * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro) 863 */ 864 Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, 865 AmlMaxFixed max_fixed, AmlCacheble cacheable, 866 AmlReadAndWrite read_and_write, 867 uint32_t addr_gran, uint32_t addr_min, 868 uint32_t addr_max, uint32_t addr_trans, 869 uint32_t len) 870 { 871 uint8_t flags = read_and_write | (cacheable << 1); 872 873 return aml_dword_as_desc(aml_memory_range, min_fixed, max_fixed, 874 dec, addr_gran, addr_min, addr_max, 875 addr_trans, len, flags); 876 } 877 878 /* 879 * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor 880 * 881 * More verbose description at: 882 * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro) 883 */ 884 Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, 885 AmlMaxFixed max_fixed, AmlCacheble cacheable, 886 AmlReadAndWrite read_and_write, 887 uint64_t addr_gran, uint64_t addr_min, 888 uint64_t addr_max, uint64_t addr_trans, 889 uint64_t len) 890 { 891 uint8_t flags = read_and_write | (cacheable << 1); 892 893 return aml_qword_as_desc(aml_memory_range, min_fixed, max_fixed, 894 dec, addr_gran, addr_min, addr_max, 895 addr_trans, len, flags); 896 } 897 898 void 899 build_header(GArray *linker, GArray *table_data, 900 AcpiTableHeader *h, const char *sig, int len, uint8_t rev) 901 { 902 memcpy(&h->signature, sig, 4); 903 h->length = cpu_to_le32(len); 904 h->revision = rev; 905 memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6); 906 memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4); 907 memcpy(h->oem_table_id + 4, sig, 4); 908 h->oem_revision = cpu_to_le32(1); 909 memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4); 910 h->asl_compiler_revision = cpu_to_le32(1); 911 h->checksum = 0; 912 /* Checksum to be filled in by Guest linker */ 913 bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE, 914 table_data->data, h, len, &h->checksum); 915 } 916 917 void *acpi_data_push(GArray *table_data, unsigned size) 918 { 919 unsigned off = table_data->len; 920 g_array_set_size(table_data, off + size); 921 return table_data->data + off; 922 } 923 924 unsigned acpi_data_len(GArray *table) 925 { 926 #if GLIB_CHECK_VERSION(2, 22, 0) 927 assert(g_array_get_element_size(table) == 1); 928 #endif 929 return table->len; 930 } 931 932 void acpi_add_table(GArray *table_offsets, GArray *table_data) 933 { 934 uint32_t offset = cpu_to_le32(table_data->len); 935 g_array_append_val(table_offsets, offset); 936 } 937 938 void acpi_build_tables_init(AcpiBuildTables *tables) 939 { 940 tables->rsdp = g_array_new(false, true /* clear */, 1); 941 tables->table_data = g_array_new(false, true /* clear */, 1); 942 tables->tcpalog = g_array_new(false, true /* clear */, 1); 943 tables->linker = bios_linker_loader_init(); 944 } 945 946 void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre) 947 { 948 void *linker_data = bios_linker_loader_cleanup(tables->linker); 949 g_free(linker_data); 950 g_array_free(tables->rsdp, true); 951 g_array_free(tables->table_data, true); 952 g_array_free(tables->tcpalog, mfre); 953 } 954