1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG 5 */ 6 7 #include <sys/param.h> 8 #include <sys/endian.h> 9 #include <sys/errno.h> 10 #include <sys/queue.h> 11 #include <sys/stat.h> 12 13 #include <machine/vmm.h> 14 15 #include <assert.h> 16 #include <err.h> 17 #include <libutil.h> 18 #include <stddef.h> 19 #include <stdio.h> 20 #include <vmmapi.h> 21 22 #ifndef __FreeBSD__ 23 #include <sys/hexdump.h> 24 #endif 25 26 #include "basl.h" 27 #include "config.h" 28 #include "qemu_loader.h" 29 30 struct basl_table_checksum { 31 STAILQ_ENTRY(basl_table_checksum) chain; 32 uint32_t off; 33 uint32_t start; 34 uint32_t len; 35 }; 36 37 struct basl_table_length { 38 STAILQ_ENTRY(basl_table_length) chain; 39 uint32_t off; 40 uint8_t size; 41 }; 42 43 struct basl_table_pointer { 44 STAILQ_ENTRY(basl_table_pointer) chain; 45 uint8_t src_signature[ACPI_NAMESEG_SIZE]; 46 uint32_t off; 47 uint8_t size; 48 }; 49 50 struct basl_table { 51 STAILQ_ENTRY(basl_table) chain; 52 struct vmctx *ctx; 53 uint8_t fwcfg_name[QEMU_FWCFG_MAX_NAME]; 54 void *data; 55 uint32_t len; 56 uint32_t off; 57 uint32_t alignment; 58 STAILQ_HEAD(basl_table_checksum_list, basl_table_checksum) checksums; 59 STAILQ_HEAD(basl_table_length_list, basl_table_length) lengths; 60 STAILQ_HEAD(basl_table_pointer_list, basl_table_pointer) pointers; 61 }; 62 static STAILQ_HEAD(basl_table_list, basl_table) basl_tables = STAILQ_HEAD_INITIALIZER( 63 basl_tables); 64 65 static struct qemu_loader *basl_loader; 66 static struct basl_table *rsdt; 67 static struct basl_table *xsdt; 68 static bool load_into_memory; 69 70 static __inline uint64_t 71 basl_le_dec(void *pp, size_t len) 72 { 73 assert(len <= 8); 74 75 switch (len) { 76 case 1: 77 return ((uint8_t *)pp)[0]; 78 case 2: 79 return le16dec(pp); 80 case 4: 81 return le32dec(pp); 82 case 8: 83 return le64dec(pp); 84 } 85 86 return 0; 87 } 88 89 static __inline void 90 basl_le_enc(void *pp, uint64_t val, size_t len) 91 { 92 char buf[8]; 93 94 assert(len <= 8); 95 96 le64enc(buf, val); 97 memcpy(pp, buf, len); 98 } 99 100 static int 101 basl_dump_table(const struct basl_table *const table, const bool mem) 102 { 103 const ACPI_TABLE_HEADER *const header = table->data; 104 const uint8_t *data; 105 106 if (!mem) { 107 data = table->data; 108 } else { 109 data = vm_map_gpa(table->ctx, BHYVE_ACPI_BASE + table->off, 110 table->len); 111 if (data == NULL) { 112 return (ENOMEM); 113 } 114 } 115 116 #ifdef __FreeBSD__ 117 printf("%.4s @ %8x (%s)\n", header->Signature, 118 BHYVE_ACPI_BASE + table->off, mem ? "Memory" : "FwCfg"); 119 hexdump(data, table->len, NULL, 0); 120 #else 121 (void) printf("%.4s @ %8x (%s)\n", header->Signature, 122 BHYVE_ACPI_BASE + table->off, mem ? "Memory" : "FwCfg"); 123 hexdump_t h; 124 hexdump_init(&h); 125 hexdump_set_addr(&h, BHYVE_ACPI_BASE + table->off); 126 (void) hexdump_fileh(&h, data, table->len, HDF_DEFAULT, stdout); 127 hexdump_fini(&h); 128 (void) printf("\n"); 129 #endif 130 131 return (0); 132 } 133 134 static int 135 basl_dump(const bool mem) 136 { 137 struct basl_table *table; 138 139 STAILQ_FOREACH(table, &basl_tables, chain) { 140 BASL_EXEC(basl_dump_table(table, mem)); 141 } 142 143 return (0); 144 } 145 146 void 147 basl_fill_gas(ACPI_GENERIC_ADDRESS *const gas, const uint8_t space_id, 148 const uint8_t bit_width, const uint8_t bit_offset, 149 const uint8_t access_width, const uint64_t address) 150 { 151 assert(gas != NULL); 152 153 gas->SpaceId = space_id; 154 gas->BitWidth = bit_width; 155 gas->BitOffset = bit_offset; 156 gas->AccessWidth = access_width; 157 gas->Address = htole64(address); 158 } 159 160 static int 161 basl_finish_install_guest_tables(struct basl_table *const table, uint32_t *const off) 162 { 163 void *gva; 164 165 table->off = roundup2(*off, table->alignment); 166 *off = table->off + table->len; 167 if (*off <= table->off) { 168 warnx("%s: invalid table length 0x%8x @ offset 0x%8x", __func__, 169 table->len, table->off); 170 return (EFAULT); 171 } 172 173 /* Cause guest BIOS to copy the ACPI table into guest memory. */ 174 #ifdef __FreeBSD__ 175 BASL_EXEC( 176 qemu_fwcfg_add_file(table->fwcfg_name, table->len, table->data)); 177 #else 178 BASL_EXEC( 179 qemu_fwcfg_add_file((const char *)table->fwcfg_name, 180 table->len, table->data)); 181 #endif 182 BASL_EXEC(qemu_loader_alloc(basl_loader, table->fwcfg_name, 183 table->alignment, QEMU_LOADER_ALLOC_HIGH)); 184 185 if (!load_into_memory) { 186 return (0); 187 } 188 189 /* 190 * Install ACPI tables directly in guest memory for use by guests which 191 * do not boot via EFI. EFI ROMs provide a pointer to the firmware 192 * generated ACPI tables instead, but it doesn't hurt to install the 193 * tables always. 194 */ 195 gva = vm_map_gpa(table->ctx, BHYVE_ACPI_BASE + table->off, table->len); 196 if (gva == NULL) { 197 warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]", __func__, 198 (uint64_t)BHYVE_ACPI_BASE + table->off, 199 (uint64_t)BHYVE_ACPI_BASE + table->off + table->len); 200 return (ENOMEM); 201 } 202 memcpy(gva, table->data, table->len); 203 204 return (0); 205 } 206 207 static int 208 basl_finish_patch_checksums(struct basl_table *const table) 209 { 210 struct basl_table_checksum *checksum; 211 212 STAILQ_FOREACH(checksum, &table->checksums, chain) { 213 uint8_t *gva, *checksum_gva; 214 uint64_t gpa; 215 uint32_t len; 216 uint8_t sum; 217 218 len = checksum->len; 219 if (len == BASL_TABLE_CHECKSUM_LEN_FULL_TABLE) { 220 len = table->len; 221 } 222 223 assert(checksum->off < table->len); 224 assert(checksum->start < table->len); 225 assert(checksum->start + len <= table->len); 226 227 /* Cause guest BIOS to patch the checksum. */ 228 BASL_EXEC(qemu_loader_add_checksum(basl_loader, 229 table->fwcfg_name, checksum->off, checksum->start, len)); 230 231 if (!load_into_memory) { 232 continue; 233 } 234 235 /* 236 * Install ACPI tables directly in guest memory for use by 237 * guests which do not boot via EFI. EFI ROMs provide a pointer 238 * to the firmware generated ACPI tables instead, but it doesn't 239 * hurt to install the tables always. 240 */ 241 gpa = BHYVE_ACPI_BASE + table->off + checksum->start; 242 if ((gpa < BHYVE_ACPI_BASE) || 243 (gpa < BHYVE_ACPI_BASE + table->off)) { 244 warnx("%s: invalid gpa (off 0x%8x start 0x%8x)", 245 __func__, table->off, checksum->start); 246 return (EFAULT); 247 } 248 249 gva = vm_map_gpa(table->ctx, gpa, len); 250 if (gva == NULL) { 251 warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]", 252 __func__, gpa, gpa + len); 253 return (ENOMEM); 254 } 255 256 checksum_gva = gva + checksum->off; 257 if (checksum_gva < gva) { 258 warnx("%s: invalid checksum offset 0x%8x", __func__, 259 checksum->off); 260 return (EFAULT); 261 } 262 263 sum = 0; 264 for (uint32_t i = 0; i < len; ++i) { 265 sum += *(gva + i); 266 } 267 *checksum_gva = -sum; 268 } 269 270 return (0); 271 } 272 273 static struct basl_table * 274 basl_get_table_by_signature(const uint8_t signature[ACPI_NAMESEG_SIZE]) 275 { 276 struct basl_table *table; 277 278 STAILQ_FOREACH(table, &basl_tables, chain) { 279 const ACPI_TABLE_HEADER *const header = 280 (const ACPI_TABLE_HEADER *)table->data; 281 282 #ifdef __FreeBSD__ 283 if (strncmp(header->Signature, signature, 284 sizeof(header->Signature)) == 0) { 285 return (table); 286 #else 287 if (strncmp(header->Signature, (char *)signature, 288 sizeof(header->Signature)) == 0) { 289 return (table); 290 #endif 291 } 292 } 293 294 warnx("%s: %.4s not found", __func__, signature); 295 return (NULL); 296 } 297 298 static int 299 basl_finish_patch_pointers(struct basl_table *const table) 300 { 301 struct basl_table_pointer *pointer; 302 303 STAILQ_FOREACH(pointer, &table->pointers, chain) { 304 const struct basl_table *src_table; 305 uint8_t *gva; 306 uint64_t gpa, val; 307 308 assert(pointer->off < table->len); 309 assert(pointer->off + pointer->size <= table->len); 310 311 src_table = basl_get_table_by_signature(pointer->src_signature); 312 if (src_table == NULL) { 313 warnx("%s: could not find ACPI table %.4s", __func__, 314 pointer->src_signature); 315 return (EFAULT); 316 } 317 318 /* Cause guest BIOS to patch the pointer. */ 319 BASL_EXEC( 320 qemu_loader_add_pointer(basl_loader, table->fwcfg_name, 321 src_table->fwcfg_name, pointer->off, pointer->size)); 322 323 if (!load_into_memory) { 324 continue; 325 } 326 327 /* 328 * Install ACPI tables directly in guest memory for use by 329 * guests which do not boot via EFI. EFI ROMs provide a pointer 330 * to the firmware generated ACPI tables instead, but it doesn't 331 * hurt to install the tables always. 332 */ 333 gpa = BHYVE_ACPI_BASE + table->off; 334 if (gpa < BHYVE_ACPI_BASE) { 335 warnx("%s: table offset of 0x%8x is too large", 336 __func__, table->off); 337 return (EFAULT); 338 } 339 340 gva = vm_map_gpa(table->ctx, gpa, table->len); 341 if (gva == NULL) { 342 warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]", 343 __func__, gpa, gpa + table->len); 344 return (ENOMEM); 345 } 346 347 val = basl_le_dec(gva + pointer->off, pointer->size); 348 val += BHYVE_ACPI_BASE + src_table->off; 349 basl_le_enc(gva + pointer->off, val, pointer->size); 350 } 351 352 return (0); 353 } 354 355 static int 356 basl_finish_set_length(struct basl_table *const table) 357 { 358 struct basl_table_length *length; 359 360 STAILQ_FOREACH(length, &table->lengths, chain) { 361 assert(length->off < table->len); 362 assert(length->off + length->size <= table->len); 363 364 basl_le_enc((uint8_t *)table->data + length->off, table->len, 365 length->size); 366 } 367 368 return (0); 369 } 370 371 int 372 basl_finish(void) 373 { 374 struct basl_table *table; 375 uint32_t off = 0; 376 377 if (STAILQ_EMPTY(&basl_tables)) { 378 warnx("%s: no ACPI tables found", __func__); 379 return (EINVAL); 380 } 381 382 /* 383 * If we install ACPI tables by FwCfg and by memory, Windows will use 384 * the tables from memory. This can cause issues when using advanced 385 * features like a TPM log because we aren't able to patch the memory 386 * tables accordingly. 387 */ 388 load_into_memory = get_config_bool_default("acpi_tables_in_memory", 389 true); 390 391 #ifndef __FreeBSD__ 392 if (get_config_bool_default("basl.debug", false)) 393 basl_dump(false); 394 #endif 395 396 /* 397 * We have to install all tables before we can patch them. Therefore, 398 * use two loops. The first one installs all tables and the second one 399 * patches them. 400 */ 401 STAILQ_FOREACH(table, &basl_tables, chain) { 402 BASL_EXEC(basl_finish_set_length(table)); 403 BASL_EXEC(basl_finish_install_guest_tables(table, &off)); 404 } 405 STAILQ_FOREACH(table, &basl_tables, chain) { 406 BASL_EXEC(basl_finish_patch_pointers(table)); 407 408 /* 409 * Calculate the checksum as last step! 410 */ 411 BASL_EXEC(basl_finish_patch_checksums(table)); 412 } 413 BASL_EXEC(qemu_loader_finish(basl_loader)); 414 415 #ifndef __FreeBSD__ 416 if (get_config_bool_default("basl.debug", false)) 417 basl_dump(true); 418 #endif 419 420 return (0); 421 } 422 423 static int 424 basl_init_rsdt(struct vmctx *const ctx) 425 { 426 BASL_EXEC( 427 basl_table_create(&rsdt, ctx, ACPI_SIG_RSDT, BASL_TABLE_ALIGNMENT)); 428 429 /* Header */ 430 BASL_EXEC(basl_table_append_header(rsdt, ACPI_SIG_RSDT, 1, 1)); 431 /* Pointers (added by basl_table_register_to_rsdt) */ 432 433 return (0); 434 } 435 436 static int 437 basl_init_xsdt(struct vmctx *const ctx) 438 { 439 BASL_EXEC( 440 basl_table_create(&xsdt, ctx, ACPI_SIG_XSDT, BASL_TABLE_ALIGNMENT)); 441 442 /* Header */ 443 BASL_EXEC(basl_table_append_header(xsdt, ACPI_SIG_XSDT, 1, 1)); 444 /* Pointers (added by basl_table_register_to_rsdt) */ 445 446 return (0); 447 } 448 449 int 450 basl_init(struct vmctx *const ctx) 451 { 452 BASL_EXEC(basl_init_rsdt(ctx)); 453 BASL_EXEC(basl_init_xsdt(ctx)); 454 #ifdef __FreeBSD__ 455 BASL_EXEC( 456 qemu_loader_create(&basl_loader, QEMU_FWCFG_FILE_TABLE_LOADER)); 457 #else 458 BASL_EXEC( 459 qemu_loader_create(&basl_loader, 460 (uint8_t *)QEMU_FWCFG_FILE_TABLE_LOADER)); 461 #endif 462 463 return (0); 464 } 465 466 int 467 basl_table_add_checksum(struct basl_table *const table, const uint32_t off, 468 const uint32_t start, const uint32_t len) 469 { 470 struct basl_table_checksum *checksum; 471 472 assert(table != NULL); 473 474 checksum = calloc(1, sizeof(struct basl_table_checksum)); 475 if (checksum == NULL) { 476 warnx("%s: failed to allocate checksum", __func__); 477 return (ENOMEM); 478 } 479 480 checksum->off = off; 481 checksum->start = start; 482 checksum->len = len; 483 484 STAILQ_INSERT_TAIL(&table->checksums, checksum, chain); 485 486 return (0); 487 } 488 489 int 490 basl_table_add_length(struct basl_table *const table, const uint32_t off, 491 const uint8_t size) 492 { 493 struct basl_table_length *length; 494 495 assert(table != NULL); 496 assert(size == 4 || size == 8); 497 498 length = calloc(1, sizeof(struct basl_table_length)); 499 if (length == NULL) { 500 warnx("%s: failed to allocate length", __func__); 501 return (ENOMEM); 502 } 503 504 length->off = off; 505 length->size = size; 506 507 STAILQ_INSERT_TAIL(&table->lengths, length, chain); 508 509 return (0); 510 } 511 512 int 513 basl_table_add_pointer(struct basl_table *const table, 514 const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint32_t off, 515 const uint8_t size) 516 { 517 struct basl_table_pointer *pointer; 518 519 assert(table != NULL); 520 assert(size == 4 || size == 8); 521 522 pointer = calloc(1, sizeof(struct basl_table_pointer)); 523 if (pointer == NULL) { 524 warnx("%s: failed to allocate pointer", __func__); 525 return (ENOMEM); 526 } 527 528 memcpy(pointer->src_signature, src_signature, 529 sizeof(pointer->src_signature)); 530 pointer->off = off; 531 pointer->size = size; 532 533 STAILQ_INSERT_TAIL(&table->pointers, pointer, chain); 534 535 return (0); 536 } 537 538 int 539 basl_table_append_bytes(struct basl_table *const table, const void *const bytes, 540 const uint32_t len) 541 { 542 void *end; 543 544 assert(table != NULL); 545 assert(bytes != NULL); 546 547 if (table->len + len <= table->len) { 548 warnx("%s: table too large (table->len 0x%8x len 0x%8x)", 549 __func__, table->len, len); 550 return (EFAULT); 551 } 552 553 table->data = reallocf(table->data, table->len + len); 554 if (table->data == NULL) { 555 warnx("%s: failed to realloc table to length 0x%8x", __func__, 556 table->len + len); 557 table->len = 0; 558 return (ENOMEM); 559 } 560 561 end = (uint8_t *)table->data + table->len; 562 table->len += len; 563 564 memcpy(end, bytes, len); 565 566 return (0); 567 } 568 569 int 570 basl_table_append_checksum(struct basl_table *const table, const uint32_t start, 571 const uint32_t len) 572 { 573 assert(table != NULL); 574 575 BASL_EXEC(basl_table_add_checksum(table, table->len, start, len)); 576 BASL_EXEC(basl_table_append_int(table, 0, 1)); 577 578 return (0); 579 } 580 581 int 582 basl_table_append_content(struct basl_table *table, void *data, uint32_t len) 583 { 584 assert(data != NULL); 585 assert(len >= sizeof(ACPI_TABLE_HEADER)); 586 587 return (basl_table_append_bytes(table, 588 (void *)((uintptr_t)(data) + sizeof(ACPI_TABLE_HEADER)), 589 len - sizeof(ACPI_TABLE_HEADER))); 590 } 591 592 int 593 basl_table_append_fwcfg(struct basl_table *const table, 594 const uint8_t *fwcfg_name, const uint32_t alignment, const uint8_t size) 595 { 596 assert(table != NULL); 597 assert(fwcfg_name != NULL); 598 assert(size <= sizeof(uint64_t)); 599 600 BASL_EXEC(qemu_loader_alloc(basl_loader, fwcfg_name, alignment, 601 QEMU_LOADER_ALLOC_HIGH)); 602 BASL_EXEC(qemu_loader_add_pointer(basl_loader, table->fwcfg_name, 603 fwcfg_name, table->len, size)); 604 BASL_EXEC(basl_table_append_int(table, 0, size)); 605 606 return (0); 607 } 608 609 int 610 basl_table_append_gas(struct basl_table *const table, const uint8_t space_id, 611 const uint8_t bit_width, const uint8_t bit_offset, 612 const uint8_t access_width, const uint64_t address) 613 { 614 ACPI_GENERIC_ADDRESS gas_le = { 615 .SpaceId = space_id, 616 .BitWidth = bit_width, 617 .BitOffset = bit_offset, 618 .AccessWidth = access_width, 619 .Address = htole64(address), 620 }; 621 622 return (basl_table_append_bytes(table, &gas_le, sizeof(gas_le))); 623 } 624 625 int 626 basl_table_append_header(struct basl_table *const table, 627 const uint8_t signature[ACPI_NAMESEG_SIZE], const uint8_t revision, 628 const uint32_t oem_revision) 629 { 630 ACPI_TABLE_HEADER header_le; 631 /* + 1 is required for the null terminator */ 632 char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; 633 634 assert(table != NULL); 635 assert(table->len == 0); 636 637 memcpy(header_le.Signature, signature, ACPI_NAMESEG_SIZE); 638 header_le.Length = 0; /* patched by basl_finish */ 639 header_le.Revision = revision; 640 header_le.Checksum = 0; /* patched by basl_finish */ 641 memcpy(header_le.OemId, "BHYVE ", ACPI_OEM_ID_SIZE); 642 snprintf(oem_table_id, ACPI_OEM_TABLE_ID_SIZE, "BV%.4s ", signature); 643 memcpy(header_le.OemTableId, oem_table_id, 644 sizeof(header_le.OemTableId)); 645 header_le.OemRevision = htole32(oem_revision); 646 memcpy(header_le.AslCompilerId, "BASL", ACPI_NAMESEG_SIZE); 647 header_le.AslCompilerRevision = htole32(0x20220504); 648 649 BASL_EXEC( 650 basl_table_append_bytes(table, &header_le, sizeof(header_le))); 651 652 BASL_EXEC(basl_table_add_length(table, 653 offsetof(ACPI_TABLE_HEADER, Length), sizeof(header_le.Length))); 654 BASL_EXEC(basl_table_add_checksum(table, 655 offsetof(ACPI_TABLE_HEADER, Checksum), 0, 656 BASL_TABLE_CHECKSUM_LEN_FULL_TABLE)); 657 658 return (0); 659 } 660 661 int 662 basl_table_append_int(struct basl_table *const table, const uint64_t val, 663 const uint8_t size) 664 { 665 char buf[8]; 666 667 assert(size <= sizeof(val)); 668 669 basl_le_enc(buf, val, size); 670 return (basl_table_append_bytes(table, buf, size)); 671 } 672 673 int 674 basl_table_append_length(struct basl_table *const table, const uint8_t size) 675 { 676 assert(table != NULL); 677 assert(size <= sizeof(table->len)); 678 679 BASL_EXEC(basl_table_add_length(table, table->len, size)); 680 BASL_EXEC(basl_table_append_int(table, 0, size)); 681 682 return (0); 683 } 684 685 int 686 basl_table_append_pointer(struct basl_table *const table, 687 const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint8_t size) 688 { 689 assert(table != NULL); 690 assert(size == 4 || size == 8); 691 692 BASL_EXEC(basl_table_add_pointer(table, src_signature, table->len, size)); 693 BASL_EXEC(basl_table_append_int(table, 0, size)); 694 695 return (0); 696 } 697 698 int 699 basl_table_create(struct basl_table **const table, struct vmctx *ctx, 700 const uint8_t *const name, const uint32_t alignment) 701 { 702 struct basl_table *new_table; 703 704 assert(table != NULL); 705 706 new_table = calloc(1, sizeof(struct basl_table)); 707 if (new_table == NULL) { 708 warnx("%s: failed to allocate table", __func__); 709 return (ENOMEM); 710 } 711 712 new_table->ctx = ctx; 713 714 #ifdef __FreeBSD__ 715 snprintf(new_table->fwcfg_name, sizeof(new_table->fwcfg_name), 716 "etc/acpi/%s", name); 717 #else 718 snprintf((char *)new_table->fwcfg_name, sizeof (new_table->fwcfg_name), 719 "etc/acpi/%s", name); 720 #endif 721 722 new_table->alignment = alignment; 723 724 STAILQ_INIT(&new_table->checksums); 725 STAILQ_INIT(&new_table->lengths); 726 STAILQ_INIT(&new_table->pointers); 727 728 STAILQ_INSERT_TAIL(&basl_tables, new_table, chain); 729 730 *table = new_table; 731 732 return (0); 733 } 734 735 int 736 basl_table_register_to_rsdt(struct basl_table *table) 737 { 738 const ACPI_TABLE_HEADER *header; 739 740 assert(table != NULL); 741 742 header = (const ACPI_TABLE_HEADER *)table->data; 743 744 #ifdef __FreeBSD__ 745 BASL_EXEC(basl_table_append_pointer(rsdt, header->Signature, 746 ACPI_RSDT_ENTRY_SIZE)); 747 BASL_EXEC(basl_table_append_pointer(xsdt, header->Signature, 748 ACPI_XSDT_ENTRY_SIZE)); 749 #else 750 BASL_EXEC(basl_table_append_pointer(rsdt, (uint8_t *)header->Signature, 751 ACPI_RSDT_ENTRY_SIZE)); 752 BASL_EXEC(basl_table_append_pointer(xsdt, (uint8_t *)header->Signature, 753 ACPI_XSDT_ENTRY_SIZE)); 754 #endif 755 756 return (0); 757 } 758