1 /****************************************************************************** 2 * 3 * Module Name: dttable1.c - handling for specific ACPI tables 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2025, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 /* Compile all complex data tables, signatures starting with A-I */ 45 46 #include "aslcompiler.h" 47 48 #define _COMPONENT DT_COMPILER 49 ACPI_MODULE_NAME ("dttable1") 50 51 52 static ACPI_DMTABLE_INFO TableInfoAsfAddress[] = 53 { 54 {ACPI_DMT_BUFFER, 0, "Addresses", 0}, 55 {ACPI_DMT_EXIT, 0, NULL, 0} 56 }; 57 58 static ACPI_DMTABLE_INFO TableInfoDmarPciPath[] = 59 { 60 {ACPI_DMT_PCI_PATH, 0, "PCI Path", 0}, 61 {ACPI_DMT_EXIT, 0, NULL, 0} 62 }; 63 64 65 /****************************************************************************** 66 * 67 * FUNCTION: DtCompileAest 68 * 69 * PARAMETERS: List - Current field list pointer 70 * 71 * RETURN: Status 72 * 73 * DESCRIPTION: Compile AEST. 74 * 75 * NOTE: Assumes the following table structure: 76 * For all AEST Error Nodes: 77 * 1) An AEST Error Node, followed immediately by: 78 * 2) Any node-specific data 79 * 3) An Interface Structure (one) 80 * 4) A list (array) of Interrupt Structures, the count as specified 81 * in the NodeInterruptCount field of the Error Node header. 82 * 83 * AEST - ARM Error Source table. Conforms to: 84 * ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document Sep 2020 85 * 86 *****************************************************************************/ 87 88 ACPI_STATUS 89 DtCompileAest ( 90 void **List) 91 { 92 ACPI_AEST_HEADER *ErrorNodeHeader; 93 ACPI_AEST_PROCESSOR *AestProcessor; 94 DT_SUBTABLE *Subtable; 95 DT_SUBTABLE *ParentTable; 96 ACPI_DMTABLE_INFO *InfoTable; 97 ACPI_STATUS Status; 98 UINT32 i; 99 UINT32 Offset; 100 DT_FIELD **PFieldList = (DT_FIELD **) List; 101 ACPI_AEST_NODE_INTERFACE_HEADER *AestNodeHeader; 102 UINT8 Revision; 103 ACPI_TABLE_HEADER *Header; 104 105 ParentTable = DtPeekSubtable (); 106 107 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 108 Revision = Header->Revision; 109 110 while (*PFieldList) 111 { 112 /* Compile the common error node header */ 113 114 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestHdr, 115 &Subtable); 116 if (ACPI_FAILURE (Status)) 117 { 118 return (Status); 119 } 120 121 ParentTable = DtPeekSubtable (); 122 DtInsertSubtable (ParentTable, Subtable); 123 124 /* Everything past the error node header will be a subtable */ 125 126 DtPushSubtable (Subtable); 127 128 /* 129 * Compile the node-specific structure (Based on the error 130 * node header Type field) 131 */ 132 ErrorNodeHeader = ACPI_CAST_PTR (ACPI_AEST_HEADER, Subtable->Buffer); 133 134 /* Point past the common error node header */ 135 136 Offset = sizeof (ACPI_AEST_HEADER); 137 ErrorNodeHeader->NodeSpecificOffset = Offset; 138 139 /* Decode the error node type */ 140 141 switch (ErrorNodeHeader->Type) 142 { 143 case ACPI_AEST_PROCESSOR_ERROR_NODE: 144 145 InfoTable = AcpiDmTableInfoAestProcError; 146 break; 147 148 case ACPI_AEST_MEMORY_ERROR_NODE: 149 150 InfoTable = AcpiDmTableInfoAestMemError; 151 break; 152 153 case ACPI_AEST_SMMU_ERROR_NODE: 154 155 InfoTable = AcpiDmTableInfoAestSmmuError; 156 break; 157 158 case ACPI_AEST_VENDOR_ERROR_NODE: 159 switch (Revision) 160 { 161 case 1: 162 InfoTable = AcpiDmTableInfoAestVendorError; 163 break; 164 165 case 2: 166 InfoTable = AcpiDmTableInfoAestVendorV2Error; 167 break; 168 169 default: 170 AcpiOsPrintf ("Unknown AEST Vendor Error Revision: %X\n", 171 Revision); 172 return (AE_ERROR); 173 } 174 break; 175 176 case ACPI_AEST_GIC_ERROR_NODE: 177 178 InfoTable = AcpiDmTableInfoAestGicError; 179 break; 180 181 case ACPI_AEST_PCIE_ERROR_NODE: 182 183 InfoTable = AcpiDmTableInfoAestPCIeError; 184 break; 185 186 case ACPI_AEST_PROXY_ERROR_NODE: 187 188 InfoTable = AcpiDmTableInfoAestProxyError; 189 break; 190 191 /* Error case below */ 192 default: 193 AcpiOsPrintf ("Unknown AEST Subtable Type: %X\n", 194 ErrorNodeHeader->Type); 195 return (AE_ERROR); 196 } 197 198 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 199 if (ACPI_FAILURE (Status)) 200 { 201 return (Status); 202 } 203 204 /* Point past the node-specific structure */ 205 206 Offset += Subtable->Length; 207 ErrorNodeHeader->NodeInterfaceOffset = Offset; 208 209 ParentTable = DtPeekSubtable (); 210 DtInsertSubtable (ParentTable, Subtable); 211 212 /* Compile any additional node-specific substructures */ 213 214 if (ErrorNodeHeader->Type == ACPI_AEST_PROCESSOR_ERROR_NODE) 215 { 216 /* 217 * Special handling for PROCESSOR_ERROR_NODE subtables 218 * (to handle the Resource Substructure via the ResourceType 219 * field). 220 */ 221 AestProcessor = ACPI_CAST_PTR (ACPI_AEST_PROCESSOR, 222 Subtable->Buffer); 223 224 switch (AestProcessor->ResourceType) 225 { 226 case ACPI_AEST_CACHE_RESOURCE: 227 228 InfoTable = AcpiDmTableInfoAestCacheRsrc; 229 break; 230 231 case ACPI_AEST_TLB_RESOURCE: 232 233 InfoTable = AcpiDmTableInfoAestTlbRsrc; 234 break; 235 236 case ACPI_AEST_GENERIC_RESOURCE: 237 238 InfoTable = AcpiDmTableInfoAestGenRsrc; 239 AcpiOsPrintf ("Generic Resource Type (%X) is not supported at this time\n", 240 AestProcessor->ResourceType); 241 return (AE_ERROR); 242 243 /* Error case below */ 244 default: 245 AcpiOsPrintf ("Unknown AEST Processor Resource Type: %X\n", 246 AestProcessor->ResourceType); 247 return (AE_ERROR); 248 } 249 250 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 251 if (ACPI_FAILURE (Status)) 252 { 253 return (Status); 254 } 255 256 /* Point past the resource substructure subtable */ 257 258 Offset += Subtable->Length; 259 ErrorNodeHeader->NodeInterfaceOffset = Offset; 260 261 ParentTable = DtPeekSubtable (); 262 DtInsertSubtable (ParentTable, Subtable); 263 } 264 265 /* Compile the (required) node interface structure */ 266 if (Revision == 1) 267 { 268 InfoTable = AcpiDmTableInfoAestXface; 269 } 270 else if (Revision == 2) 271 { 272 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXfaceHeader, 273 &Subtable); 274 if (ACPI_FAILURE (Status)) 275 { 276 return (Status); 277 } 278 279 ParentTable = DtPeekSubtable (); 280 DtInsertSubtable (ParentTable, Subtable); 281 282 Offset += Subtable->Length; 283 284 AestNodeHeader = ACPI_CAST_PTR (ACPI_AEST_NODE_INTERFACE_HEADER, 285 Subtable->Buffer); 286 287 switch (AestNodeHeader->GroupFormat) 288 { 289 case ACPI_AEST_NODE_GROUP_FORMAT_4K: 290 291 InfoTable = AcpiDmTableInfoAestXface4k; 292 break; 293 294 case ACPI_AEST_NODE_GROUP_FORMAT_16K: 295 296 InfoTable = AcpiDmTableInfoAestXface16k; 297 break; 298 299 case ACPI_AEST_NODE_GROUP_FORMAT_64K: 300 301 InfoTable = AcpiDmTableInfoAestXface64k; 302 break; 303 304 /* Error case below */ 305 default: 306 AcpiOsPrintf ("Unknown AEST Interface Group Format: %X\n", 307 AestNodeHeader->GroupFormat); 308 return (AE_ERROR); 309 } 310 } 311 else 312 { 313 AcpiOsPrintf ("Unknown AEST Revision: %X\n", Revision); 314 } 315 316 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 317 if (ACPI_FAILURE (Status)) 318 { 319 return (Status); 320 } 321 322 ErrorNodeHeader->NodeInterruptOffset = 0; 323 ParentTable = DtPeekSubtable (); 324 DtInsertSubtable (ParentTable, Subtable); 325 326 /* Compile each of the node interrupt structures */ 327 328 if (ErrorNodeHeader->NodeInterruptCount) 329 { 330 /* Point to the first interrupt structure */ 331 332 Offset += Subtable->Length; 333 ErrorNodeHeader->NodeInterruptOffset = Offset; 334 } 335 336 /* Compile each of the interrupt structures */ 337 338 for (i = 0; i < ErrorNodeHeader->NodeInterruptCount; i++) 339 { 340 switch (Revision) { 341 case 1: 342 343 InfoTable = AcpiDmTableInfoAestXrupt; 344 break; 345 346 case 2: 347 348 InfoTable = AcpiDmTableInfoAestXruptV2; 349 break; 350 351 default: 352 AcpiOsPrintf ("Unknown AEST Revision: %X\n", Revision); 353 return (AE_ERROR); 354 } 355 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 356 if (ACPI_FAILURE (Status)) 357 { 358 return (Status); 359 } 360 361 ParentTable = DtPeekSubtable (); 362 DtInsertSubtable (ParentTable, Subtable); 363 } 364 365 /* Prepare for the next AEST Error node */ 366 367 DtPopSubtable (); 368 } 369 370 return (AE_OK); 371 } 372 373 374 /****************************************************************************** 375 * 376 * FUNCTION: DtCompileApmt 377 * 378 * PARAMETERS: List - Current field list pointer 379 * 380 * RETURN: Status 381 * 382 * DESCRIPTION: Compile APMT. 383 * 384 *****************************************************************************/ 385 386 ACPI_STATUS 387 DtCompileApmt ( 388 void **List) 389 { 390 ACPI_STATUS Status; 391 ACPI_TABLE_HEADER *Header; 392 ACPI_APMT_NODE *ApmtNode; 393 ACPI_APMT_NODE *PeerApmtNode; 394 DT_SUBTABLE *Subtable; 395 DT_SUBTABLE *PeerSubtable; 396 DT_SUBTABLE *ParentTable; 397 DT_FIELD **PFieldList = (DT_FIELD**)List; 398 DT_FIELD *SubtableStart; 399 UINT32 CurLength; 400 char MsgBuffer[64] = ""; 401 402 ParentTable = DtPeekSubtable(); 403 404 Header = ACPI_CAST_PTR(ACPI_TABLE_HEADER, ParentTable->Buffer); 405 406 CurLength = sizeof(ACPI_TABLE_HEADER); 407 408 /* Walk the parse tree */ 409 410 while (*PFieldList) 411 { 412 /* APMT Node Subtable */ 413 414 SubtableStart = *PFieldList; 415 416 Status = DtCompileTable(PFieldList, AcpiDmTableInfoApmtNode, &Subtable); 417 418 if (ACPI_FAILURE(Status)) 419 { 420 return (Status); 421 } 422 423 ApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, Subtable->Buffer); 424 425 if (ApmtNode->Length != sizeof(ACPI_APMT_NODE)) 426 { 427 DtFatal(ASL_MSG_INVALID_LENGTH, SubtableStart, "APMT"); 428 return (AE_ERROR); 429 } 430 431 if (ApmtNode->Type >= ACPI_APMT_NODE_TYPE_COUNT) 432 { 433 snprintf(MsgBuffer, 64, "Node Type : 0x%X", ApmtNode->Type); 434 DtFatal(ASL_MSG_INVALID_TYPE, SubtableStart, MsgBuffer); 435 return (AE_ERROR); 436 } 437 438 PeerSubtable = DtGetNextSubtable(ParentTable, NULL); 439 440 /* Validate the node id needs to be unique. */ 441 while(PeerSubtable) 442 { 443 PeerApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, PeerSubtable->Buffer); 444 if (PeerApmtNode->Id == ApmtNode->Id) 445 { 446 snprintf(MsgBuffer, 64, "Node Id : 0x%X existed", ApmtNode->Id); 447 DtFatal(ASL_MSG_DUPLICATE_ITEM, SubtableStart, MsgBuffer); 448 return (AE_ERROR); 449 } 450 451 PeerSubtable = DtGetNextSubtable(ParentTable, PeerSubtable); 452 } 453 454 CurLength += ApmtNode->Length; 455 456 DtInsertSubtable(ParentTable, Subtable); 457 } 458 459 if (Header->Length != CurLength) 460 { 461 snprintf(MsgBuffer, 64, " - APMT Length : %u (expected: %u)", 462 Header->Length, CurLength); 463 DtFatal(ASL_MSG_INVALID_LENGTH, NULL, MsgBuffer); 464 return (AE_ERROR); 465 } 466 467 return (AE_OK); 468 } 469 470 /****************************************************************************** 471 * 472 * FUNCTION: DtCompileAsf 473 * 474 * PARAMETERS: List - Current field list pointer 475 * 476 * RETURN: Status 477 * 478 * DESCRIPTION: Compile ASF!. 479 * 480 *****************************************************************************/ 481 482 ACPI_STATUS 483 DtCompileAsf ( 484 void **List) 485 { 486 ACPI_ASF_INFO *AsfTable; 487 DT_SUBTABLE *Subtable; 488 DT_SUBTABLE *ParentTable; 489 ACPI_DMTABLE_INFO *InfoTable; 490 ACPI_DMTABLE_INFO *DataInfoTable = NULL; 491 UINT32 DataCount = 0; 492 ACPI_STATUS Status; 493 UINT32 i; 494 DT_FIELD **PFieldList = (DT_FIELD **) List; 495 DT_FIELD *SubtableStart; 496 497 498 while (*PFieldList) 499 { 500 SubtableStart = *PFieldList; 501 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr, 502 &Subtable); 503 if (ACPI_FAILURE (Status)) 504 { 505 return (Status); 506 } 507 508 ParentTable = DtPeekSubtable (); 509 DtInsertSubtable (ParentTable, Subtable); 510 DtPushSubtable (Subtable); 511 512 AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer); 513 514 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ 515 { 516 case ACPI_ASF_TYPE_INFO: 517 518 InfoTable = AcpiDmTableInfoAsf0; 519 break; 520 521 case ACPI_ASF_TYPE_ALERT: 522 523 InfoTable = AcpiDmTableInfoAsf1; 524 break; 525 526 case ACPI_ASF_TYPE_CONTROL: 527 528 InfoTable = AcpiDmTableInfoAsf2; 529 break; 530 531 case ACPI_ASF_TYPE_BOOT: 532 533 InfoTable = AcpiDmTableInfoAsf3; 534 break; 535 536 case ACPI_ASF_TYPE_ADDRESS: 537 538 InfoTable = AcpiDmTableInfoAsf4; 539 break; 540 541 default: 542 543 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); 544 return (AE_ERROR); 545 } 546 547 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 548 if (ACPI_FAILURE (Status)) 549 { 550 return (Status); 551 } 552 553 ParentTable = DtPeekSubtable (); 554 DtInsertSubtable (ParentTable, Subtable); 555 556 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ 557 { 558 case ACPI_ASF_TYPE_INFO: 559 560 DataInfoTable = NULL; 561 break; 562 563 case ACPI_ASF_TYPE_ALERT: 564 565 DataInfoTable = AcpiDmTableInfoAsf1a; 566 DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT, 567 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 568 sizeof (ACPI_ASF_HEADER)))->Alerts; 569 break; 570 571 case ACPI_ASF_TYPE_CONTROL: 572 573 DataInfoTable = AcpiDmTableInfoAsf2a; 574 DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE, 575 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 576 sizeof (ACPI_ASF_HEADER)))->Controls; 577 break; 578 579 case ACPI_ASF_TYPE_BOOT: 580 581 DataInfoTable = NULL; 582 break; 583 584 case ACPI_ASF_TYPE_ADDRESS: 585 586 DataInfoTable = TableInfoAsfAddress; 587 DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS, 588 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 589 sizeof (ACPI_ASF_HEADER)))->Devices; 590 break; 591 592 default: 593 594 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); 595 return (AE_ERROR); 596 } 597 598 if (DataInfoTable) 599 { 600 switch (AsfTable->Header.Type & 0x7F) 601 { 602 case ACPI_ASF_TYPE_ADDRESS: 603 604 while (DataCount > 0) 605 { 606 Status = DtCompileTable (PFieldList, DataInfoTable, 607 &Subtable); 608 if (ACPI_FAILURE (Status)) 609 { 610 return (Status); 611 } 612 613 DtInsertSubtable (ParentTable, Subtable); 614 DataCount = DataCount - Subtable->Length; 615 } 616 break; 617 618 default: 619 620 for (i = 0; i < DataCount; i++) 621 { 622 Status = DtCompileTable (PFieldList, DataInfoTable, 623 &Subtable); 624 if (ACPI_FAILURE (Status)) 625 { 626 return (Status); 627 } 628 629 DtInsertSubtable (ParentTable, Subtable); 630 } 631 break; 632 } 633 } 634 635 DtPopSubtable (); 636 } 637 638 return (AE_OK); 639 } 640 641 /****************************************************************************** 642 * 643 * FUNCTION: DtCompileAspt 644 * 645 * PARAMETERS: List - Current field list pointer 646 * 647 * RETURN: Status 648 * 649 * DESCRIPTION: Compile ASPT. 650 * 651 *****************************************************************************/ 652 653 ACPI_STATUS 654 DtCompileAspt ( 655 void **List) 656 { 657 ACPI_ASPT_HEADER *AsptTable; 658 DT_SUBTABLE *Subtable; 659 DT_SUBTABLE *ParentTable; 660 ACPI_DMTABLE_INFO *InfoTable; 661 ACPI_STATUS Status; 662 DT_FIELD **PFieldList = (DT_FIELD **) List; 663 DT_FIELD *SubtableStart; 664 665 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAspt, &Subtable); 666 if (ACPI_FAILURE (Status)) 667 { 668 return (Status); 669 } 670 671 ParentTable = DtPeekSubtable (); 672 DtInsertSubtable (ParentTable, Subtable); 673 674 while (*PFieldList) 675 { 676 SubtableStart = *PFieldList; 677 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsptHdr, 678 &Subtable); 679 if (ACPI_FAILURE (Status)) 680 { 681 return (Status); 682 } 683 684 ParentTable = DtPeekSubtable (); 685 DtInsertSubtable (ParentTable, Subtable); 686 DtPushSubtable (Subtable); 687 688 AsptTable = ACPI_CAST_PTR (ACPI_ASPT_HEADER, Subtable->Buffer); 689 690 switch (AsptTable->Type) /* Mask off top bit */ 691 { 692 case ACPI_ASPT_TYPE_GLOBAL_REGS: 693 694 InfoTable = AcpiDmTableInfoAspt0; 695 break; 696 697 case ACPI_ASPT_TYPE_SEV_MBOX_REGS: 698 699 InfoTable = AcpiDmTableInfoAspt1; 700 break; 701 702 case ACPI_ASPT_TYPE_ACPI_MBOX_REGS: 703 704 InfoTable = AcpiDmTableInfoAspt2; 705 break; 706 707 default: 708 709 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASPT"); 710 return (AE_ERROR); 711 } 712 713 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 714 if (ACPI_FAILURE (Status)) 715 { 716 return (Status); 717 } 718 ParentTable = DtPeekSubtable (); 719 DtInsertSubtable (ParentTable, Subtable); 720 DtPopSubtable (); 721 } 722 723 return (AE_OK); 724 } 725 726 727 /****************************************************************************** 728 * 729 * FUNCTION: DtCompileCdat 730 * 731 * PARAMETERS: List - Current field list pointer 732 * 733 * RETURN: Status 734 * 735 * DESCRIPTION: Compile CDAT. 736 * 737 *****************************************************************************/ 738 739 ACPI_STATUS 740 DtCompileCdat ( 741 void **List) 742 { 743 ACPI_STATUS Status = AE_OK; 744 DT_SUBTABLE *Subtable; 745 DT_SUBTABLE *ParentTable; 746 DT_FIELD **PFieldList = (DT_FIELD **) List; 747 ACPI_CDAT_HEADER *CdatHeader; 748 ACPI_DMTABLE_INFO *InfoTable = NULL; 749 DT_FIELD *SubtableStart; 750 751 752 /* Walk the parse tree. 753 * 754 * Note: Main table consists of only the CDAT table header 755 * (This is not the standard ACPI table header, however)-- 756 * Followed by some number of subtables. 757 */ 758 while (*PFieldList) 759 { 760 SubtableStart = *PFieldList; 761 762 /* Compile the expected CDAT Subtable header */ 763 764 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatHeader, 765 &Subtable); 766 if (ACPI_FAILURE (Status)) 767 { 768 return (Status); 769 } 770 771 ParentTable = DtPeekSubtable (); 772 DtInsertSubtable (ParentTable, Subtable); 773 DtPushSubtable (Subtable); 774 775 CdatHeader = ACPI_CAST_PTR (ACPI_CDAT_HEADER, Subtable->Buffer); 776 777 /* Decode the subtable by type */ 778 779 switch (CdatHeader->Type) 780 { 781 case ACPI_CDAT_TYPE_DSMAS: 782 InfoTable = AcpiDmTableInfoCdat0; 783 break; 784 785 case ACPI_CDAT_TYPE_DSLBIS: 786 InfoTable = AcpiDmTableInfoCdat1; 787 break; 788 789 case ACPI_CDAT_TYPE_DSMSCIS: 790 InfoTable = AcpiDmTableInfoCdat2; 791 break; 792 793 case ACPI_CDAT_TYPE_DSIS: 794 InfoTable = AcpiDmTableInfoCdat3; 795 break; 796 797 case ACPI_CDAT_TYPE_DSEMTS: 798 InfoTable = AcpiDmTableInfoCdat4; 799 break; 800 801 case ACPI_CDAT_TYPE_SSLBIS: 802 InfoTable = AcpiDmTableInfoCdat5; 803 break; 804 805 default: 806 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CDAT"); 807 } 808 809 /* Compile the CDAT subtable */ 810 811 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 812 if (ACPI_FAILURE (Status)) 813 { 814 return (Status); 815 } 816 817 ParentTable = DtPeekSubtable (); 818 DtInsertSubtable (ParentTable, Subtable); 819 820 switch (CdatHeader->Type) 821 { 822 /* Multiple entries supported for this type */ 823 824 case ACPI_CDAT_TYPE_SSLBIS: 825 826 /* 827 * Check for multiple SSLBEs 828 */ 829 while (*PFieldList && !AcpiUtStricmp ((*PFieldList)->Name, "Port X ID")) 830 { 831 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatEntries, &Subtable); 832 if (ACPI_FAILURE (Status)) 833 { 834 return (Status); 835 } 836 ParentTable = DtPeekSubtable (); 837 DtInsertSubtable (ParentTable, Subtable); 838 } 839 break; 840 841 default: 842 break; 843 } 844 845 /* Pop off the CDAT Subtable header subtree */ 846 847 DtPopSubtable (); 848 } 849 850 return (AE_OK); 851 } 852 853 854 /****************************************************************************** 855 * 856 * FUNCTION: DtCompileCedt 857 * 858 * PARAMETERS: List - Current field list pointer 859 * 860 * RETURN: Status 861 * 862 * DESCRIPTION: Compile CEDT. 863 * 864 *****************************************************************************/ 865 866 ACPI_STATUS 867 DtCompileCedt ( 868 void **List) 869 { 870 ACPI_STATUS Status; 871 DT_SUBTABLE *Subtable; 872 DT_SUBTABLE *ParentTable; 873 DT_FIELD **PFieldList = (DT_FIELD **) List; 874 ACPI_CEDT_HEADER *CedtHeader; 875 DT_FIELD *SubtableStart; 876 877 878 /* Walk the parse tree */ 879 880 while (*PFieldList) 881 { 882 /* if CFMWS and has more than one target, then set to zero later */ 883 884 int InsertFlag = 1; 885 SubtableStart = *PFieldList; 886 887 /* CEDT Header */ 888 889 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr, 890 &Subtable); 891 if (ACPI_FAILURE (Status)) 892 { 893 return (Status); 894 } 895 896 ParentTable = DtPeekSubtable (); 897 DtInsertSubtable (ParentTable, Subtable); 898 DtPushSubtable (Subtable); 899 900 CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer); 901 902 switch (CedtHeader->Type) 903 { 904 case ACPI_CEDT_TYPE_CHBS: 905 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable); 906 if (ACPI_FAILURE (Status)) 907 { 908 return (Status); 909 } 910 break; 911 case ACPI_CEDT_TYPE_CFMWS: { 912 unsigned char *dump; 913 unsigned int idx, offset, max = 0; 914 915 /* Compile table with first "Interleave target" */ 916 917 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1, &Subtable); 918 if (ACPI_FAILURE (Status)) 919 { 920 return (Status); 921 } 922 923 /* Look in buffer for the number of targets */ 924 offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CFMWS, InterleaveWays); 925 dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt1 */ 926 max = 0x01 << dump[offset]; /* 2^max, so 0=1, 1=2, 2=4, 3=8. 8 is MAX */ 927 if (max > 8) max=1; /* Error in encoding Interleaving Ways. */ 928 if (max == 1) /* if only one target, then break here. */ 929 break; /* break if only one target. */ 930 931 /* We need to add more interleave targets, so write the current Subtable. */ 932 933 ParentTable = DtPeekSubtable (); 934 DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt1 table so we can put in */ 935 DtPushSubtable (Subtable); /* the targets > the first. */ 936 937 /* Now, find out all interleave targets beyond the first. */ 938 939 for (idx = 1; idx < max; idx++) { 940 ParentTable = DtPeekSubtable (); 941 942 if (*PFieldList) 943 { 944 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1_te, &Subtable); 945 if (ACPI_FAILURE (Status)) 946 { 947 return (Status); 948 } 949 if (Subtable) 950 { 951 DtInsertSubtable (ParentTable, Subtable); /* got a target, so insert table. */ 952 InsertFlag = 0; 953 } 954 } 955 } 956 957 DtPopSubtable (); 958 ParentTable = DtPeekSubtable (); 959 break; 960 } 961 case ACPI_CEDT_TYPE_CXIMS: { 962 unsigned char *dump; 963 unsigned int idx, offset, max = 0; 964 965 /* Compile table with first "Xor map" */ 966 967 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt2, &Subtable); 968 if (ACPI_FAILURE (Status)) 969 { 970 return (Status); 971 } 972 973 /* Look in buffer for the number of Xor maps */ 974 offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CXIMS, NrXormaps); 975 dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt2 */ 976 max = dump[offset]; 977 978 /* We need to add more XOR maps, so write the current Subtable. */ 979 980 ParentTable = DtPeekSubtable (); 981 DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt2 table so we can put in */ 982 DtPushSubtable (Subtable); 983 984 /* Now, find out all Xor maps beyond the first. */ 985 986 for (idx = 1; idx < max; idx++) { 987 ParentTable = DtPeekSubtable (); 988 989 if (*PFieldList) 990 { 991 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt2_te, &Subtable); 992 if (ACPI_FAILURE (Status)) 993 { 994 return (Status); 995 } 996 if (Subtable) 997 { 998 DtInsertSubtable (ParentTable, Subtable); /* got an Xor map, so insert table. */ 999 InsertFlag = 0; 1000 } 1001 } 1002 } 1003 1004 DtPopSubtable (); 1005 ParentTable = DtPeekSubtable (); 1006 break; 1007 } 1008 1009 default: 1010 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT"); 1011 return (AE_ERROR); 1012 } 1013 1014 ParentTable = DtPeekSubtable (); 1015 if (InsertFlag == 1) { 1016 DtInsertSubtable (ParentTable, Subtable); 1017 } 1018 DtPopSubtable (); 1019 } 1020 1021 return (AE_OK); 1022 } 1023 1024 1025 /****************************************************************************** 1026 * 1027 * FUNCTION: DtCompileCpep 1028 * 1029 * PARAMETERS: List - Current field list pointer 1030 * 1031 * RETURN: Status 1032 * 1033 * DESCRIPTION: Compile CPEP. 1034 * 1035 *****************************************************************************/ 1036 1037 ACPI_STATUS 1038 DtCompileCpep ( 1039 void **List) 1040 { 1041 ACPI_STATUS Status; 1042 1043 1044 Status = DtCompileTwoSubtables (List, 1045 AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0); 1046 return (Status); 1047 } 1048 1049 1050 /****************************************************************************** 1051 * 1052 * FUNCTION: DtCompileCsrt 1053 * 1054 * PARAMETERS: List - Current field list pointer 1055 * 1056 * RETURN: Status 1057 * 1058 * DESCRIPTION: Compile CSRT. 1059 * 1060 *****************************************************************************/ 1061 1062 ACPI_STATUS 1063 DtCompileCsrt ( 1064 void **List) 1065 { 1066 ACPI_STATUS Status = AE_OK; 1067 DT_SUBTABLE *Subtable; 1068 DT_SUBTABLE *ParentTable; 1069 DT_FIELD **PFieldList = (DT_FIELD **) List; 1070 UINT32 DescriptorCount; 1071 UINT32 GroupLength; 1072 1073 1074 /* Subtables (Resource Groups) */ 1075 1076 ParentTable = DtPeekSubtable (); 1077 while (*PFieldList) 1078 { 1079 /* Resource group subtable */ 1080 1081 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0, 1082 &Subtable); 1083 if (ACPI_FAILURE (Status)) 1084 { 1085 return (Status); 1086 } 1087 1088 /* Compute the number of resource descriptors */ 1089 1090 GroupLength = 1091 (ACPI_CAST_PTR (ACPI_CSRT_GROUP, 1092 Subtable->Buffer))->Length - 1093 (ACPI_CAST_PTR (ACPI_CSRT_GROUP, 1094 Subtable->Buffer))->SharedInfoLength - 1095 sizeof (ACPI_CSRT_GROUP); 1096 1097 DescriptorCount = (GroupLength / 1098 sizeof (ACPI_CSRT_DESCRIPTOR)); 1099 1100 DtInsertSubtable (ParentTable, Subtable); 1101 DtPushSubtable (Subtable); 1102 ParentTable = DtPeekSubtable (); 1103 1104 /* Shared info subtable (One per resource group) */ 1105 1106 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1, 1107 &Subtable); 1108 if (ACPI_FAILURE (Status)) 1109 { 1110 return (Status); 1111 } 1112 1113 DtInsertSubtable (ParentTable, Subtable); 1114 1115 /* Sub-Subtables (Resource Descriptors) */ 1116 1117 while (*PFieldList && DescriptorCount) 1118 { 1119 1120 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2, 1121 &Subtable); 1122 if (ACPI_FAILURE (Status)) 1123 { 1124 return (Status); 1125 } 1126 1127 DtInsertSubtable (ParentTable, Subtable); 1128 1129 DtPushSubtable (Subtable); 1130 ParentTable = DtPeekSubtable (); 1131 if (*PFieldList) 1132 { 1133 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a, 1134 &Subtable); 1135 if (ACPI_FAILURE (Status)) 1136 { 1137 return (Status); 1138 } 1139 if (Subtable) 1140 { 1141 DtInsertSubtable (ParentTable, Subtable); 1142 } 1143 } 1144 1145 DtPopSubtable (); 1146 ParentTable = DtPeekSubtable (); 1147 DescriptorCount--; 1148 } 1149 1150 DtPopSubtable (); 1151 ParentTable = DtPeekSubtable (); 1152 } 1153 1154 return (Status); 1155 } 1156 1157 1158 /****************************************************************************** 1159 * 1160 * FUNCTION: DtCompileDbg2 1161 * 1162 * PARAMETERS: List - Current field list pointer 1163 * 1164 * RETURN: Status 1165 * 1166 * DESCRIPTION: Compile DBG2. 1167 * 1168 *****************************************************************************/ 1169 1170 ACPI_STATUS 1171 DtCompileDbg2 ( 1172 void **List) 1173 { 1174 ACPI_STATUS Status; 1175 DT_SUBTABLE *Subtable; 1176 DT_SUBTABLE *ParentTable; 1177 DT_FIELD **PFieldList = (DT_FIELD **) List; 1178 UINT32 SubtableCount; 1179 ACPI_DBG2_HEADER *Dbg2Header; 1180 ACPI_DBG2_DEVICE *DeviceInfo; 1181 UINT16 CurrentOffset; 1182 UINT32 i; 1183 1184 1185 /* Main table */ 1186 1187 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable); 1188 if (ACPI_FAILURE (Status)) 1189 { 1190 return (Status); 1191 } 1192 1193 ParentTable = DtPeekSubtable (); 1194 DtInsertSubtable (ParentTable, Subtable); 1195 1196 /* Main table fields */ 1197 1198 Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer); 1199 Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF ( 1200 ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header); 1201 1202 SubtableCount = Dbg2Header->InfoCount; 1203 DtPushSubtable (Subtable); 1204 1205 /* Process all Device Information subtables (Count = InfoCount) */ 1206 1207 while (*PFieldList && SubtableCount) 1208 { 1209 /* Subtable: Debug Device Information */ 1210 1211 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device, 1212 &Subtable); 1213 if (ACPI_FAILURE (Status)) 1214 { 1215 return (Status); 1216 } 1217 1218 DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer); 1219 CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE); 1220 1221 ParentTable = DtPeekSubtable (); 1222 DtInsertSubtable (ParentTable, Subtable); 1223 DtPushSubtable (Subtable); 1224 1225 ParentTable = DtPeekSubtable (); 1226 1227 /* BaseAddressRegister GAS array (Required, size is RegisterCount) */ 1228 1229 DeviceInfo->BaseAddressOffset = CurrentOffset; 1230 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) 1231 { 1232 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr, 1233 &Subtable); 1234 if (ACPI_FAILURE (Status)) 1235 { 1236 return (Status); 1237 } 1238 1239 CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS); 1240 DtInsertSubtable (ParentTable, Subtable); 1241 } 1242 1243 /* AddressSize array (Required, size = RegisterCount) */ 1244 1245 DeviceInfo->AddressSizeOffset = CurrentOffset; 1246 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) 1247 { 1248 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size, 1249 &Subtable); 1250 if (ACPI_FAILURE (Status)) 1251 { 1252 return (Status); 1253 } 1254 1255 CurrentOffset += (UINT16) sizeof (UINT32); 1256 DtInsertSubtable (ParentTable, Subtable); 1257 } 1258 1259 /* NamespaceString device identifier (Required, size = NamePathLength) */ 1260 1261 DeviceInfo->NamepathOffset = CurrentOffset; 1262 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name, 1263 &Subtable); 1264 if (ACPI_FAILURE (Status)) 1265 { 1266 return (Status); 1267 } 1268 1269 /* Update the device info header */ 1270 1271 DeviceInfo->NamepathLength = (UINT16) Subtable->Length; 1272 CurrentOffset += (UINT16) DeviceInfo->NamepathLength; 1273 DtInsertSubtable (ParentTable, Subtable); 1274 1275 /* OemData - Variable-length data (Optional, size = OemDataLength) */ 1276 1277 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData, 1278 &Subtable); 1279 if (Status == AE_END_OF_TABLE) 1280 { 1281 /* optional field was not found and we're at the end of the file */ 1282 1283 goto subtableDone; 1284 } 1285 else if (ACPI_FAILURE (Status)) 1286 { 1287 return (Status); 1288 } 1289 1290 /* Update the device info header (zeros if no OEM data present) */ 1291 1292 DeviceInfo->OemDataOffset = 0; 1293 DeviceInfo->OemDataLength = 0; 1294 1295 /* Optional subtable (OemData) */ 1296 1297 if (Subtable && Subtable->Length) 1298 { 1299 DeviceInfo->OemDataOffset = CurrentOffset; 1300 DeviceInfo->OemDataLength = (UINT16) Subtable->Length; 1301 1302 DtInsertSubtable (ParentTable, Subtable); 1303 } 1304 subtableDone: 1305 SubtableCount--; 1306 DtPopSubtable (); /* Get next Device Information subtable */ 1307 } 1308 1309 DtPopSubtable (); 1310 return (AE_OK); 1311 } 1312 1313 1314 /****************************************************************************** 1315 * 1316 * FUNCTION: DtCompileDmar 1317 * 1318 * PARAMETERS: List - Current field list pointer 1319 * 1320 * RETURN: Status 1321 * 1322 * DESCRIPTION: Compile DMAR. 1323 * 1324 *****************************************************************************/ 1325 1326 ACPI_STATUS 1327 DtCompileDmar ( 1328 void **List) 1329 { 1330 ACPI_STATUS Status; 1331 DT_SUBTABLE *Subtable; 1332 DT_SUBTABLE *ParentTable; 1333 DT_FIELD **PFieldList = (DT_FIELD **) List; 1334 DT_FIELD *SubtableStart; 1335 ACPI_DMTABLE_INFO *InfoTable; 1336 ACPI_DMAR_HEADER *DmarHeader; 1337 ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope; 1338 UINT32 DeviceScopeLength; 1339 UINT32 PciPathLength; 1340 1341 1342 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable); 1343 if (ACPI_FAILURE (Status)) 1344 { 1345 return (Status); 1346 } 1347 1348 ParentTable = DtPeekSubtable (); 1349 DtInsertSubtable (ParentTable, Subtable); 1350 DtPushSubtable (Subtable); 1351 1352 while (*PFieldList) 1353 { 1354 /* DMAR Header */ 1355 1356 SubtableStart = *PFieldList; 1357 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr, 1358 &Subtable); 1359 if (ACPI_FAILURE (Status)) 1360 { 1361 return (Status); 1362 } 1363 1364 ParentTable = DtPeekSubtable (); 1365 DtInsertSubtable (ParentTable, Subtable); 1366 DtPushSubtable (Subtable); 1367 1368 DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer); 1369 1370 switch (DmarHeader->Type) 1371 { 1372 case ACPI_DMAR_TYPE_HARDWARE_UNIT: 1373 1374 InfoTable = AcpiDmTableInfoDmar0; 1375 break; 1376 1377 case ACPI_DMAR_TYPE_RESERVED_MEMORY: 1378 1379 InfoTable = AcpiDmTableInfoDmar1; 1380 break; 1381 1382 case ACPI_DMAR_TYPE_ROOT_ATS: 1383 1384 InfoTable = AcpiDmTableInfoDmar2; 1385 break; 1386 1387 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY: 1388 1389 InfoTable = AcpiDmTableInfoDmar3; 1390 break; 1391 1392 case ACPI_DMAR_TYPE_NAMESPACE: 1393 1394 InfoTable = AcpiDmTableInfoDmar4; 1395 break; 1396 1397 case ACPI_DMAR_TYPE_SATC: 1398 1399 InfoTable = AcpiDmTableInfoDmar5; 1400 break; 1401 1402 case ACPI_DMAR_TYPE_SIDP: 1403 1404 InfoTable = AcpiDmTableInfoDmar6; 1405 break; 1406 1407 default: 1408 1409 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR"); 1410 return (AE_ERROR); 1411 } 1412 1413 /* DMAR Subtable */ 1414 1415 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1416 if (ACPI_FAILURE (Status)) 1417 { 1418 return (Status); 1419 } 1420 1421 ParentTable = DtPeekSubtable (); 1422 DtInsertSubtable (ParentTable, Subtable); 1423 1424 /* 1425 * Optional Device Scope subtables 1426 */ 1427 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) || 1428 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE)) 1429 { 1430 /* These types do not support device scopes */ 1431 1432 DtPopSubtable (); 1433 continue; 1434 } 1435 1436 DtPushSubtable (Subtable); 1437 DeviceScopeLength = DmarHeader->Length - Subtable->Length - 1438 ParentTable->Length; 1439 while (DeviceScopeLength) 1440 { 1441 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope, 1442 &Subtable); 1443 if (Status == AE_NOT_FOUND) 1444 { 1445 break; 1446 } 1447 1448 ParentTable = DtPeekSubtable (); 1449 DtInsertSubtable (ParentTable, Subtable); 1450 DtPushSubtable (Subtable); 1451 1452 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer); 1453 1454 /* Optional PCI Paths */ 1455 1456 PciPathLength = DmarDeviceScope->Length - Subtable->Length; 1457 while (PciPathLength) 1458 { 1459 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath, 1460 &Subtable); 1461 if (Status == AE_NOT_FOUND) 1462 { 1463 DtPopSubtable (); 1464 break; 1465 } 1466 1467 ParentTable = DtPeekSubtable (); 1468 DtInsertSubtable (ParentTable, Subtable); 1469 PciPathLength -= Subtable->Length; 1470 } 1471 1472 DtPopSubtable (); 1473 DeviceScopeLength -= DmarDeviceScope->Length; 1474 } 1475 1476 DtPopSubtable (); 1477 DtPopSubtable (); 1478 } 1479 1480 return (AE_OK); 1481 } 1482 1483 1484 /****************************************************************************** 1485 * 1486 * FUNCTION: DtCompileDrtm 1487 * 1488 * PARAMETERS: List - Current field list pointer 1489 * 1490 * RETURN: Status 1491 * 1492 * DESCRIPTION: Compile DRTM. 1493 * 1494 *****************************************************************************/ 1495 1496 ACPI_STATUS 1497 DtCompileDrtm ( 1498 void **List) 1499 { 1500 ACPI_STATUS Status; 1501 DT_SUBTABLE *Subtable; 1502 DT_SUBTABLE *ParentTable; 1503 DT_FIELD **PFieldList = (DT_FIELD **) List; 1504 UINT32 Count; 1505 /* ACPI_TABLE_DRTM *Drtm; */ 1506 ACPI_DRTM_VTABLE_LIST *DrtmVtl; 1507 ACPI_DRTM_RESOURCE_LIST *DrtmRl; 1508 /* ACPI_DRTM_DPS_ID *DrtmDps; */ 1509 1510 1511 ParentTable = DtPeekSubtable (); 1512 1513 /* Compile DRTM header */ 1514 1515 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm, 1516 &Subtable); 1517 if (ACPI_FAILURE (Status)) 1518 { 1519 return (Status); 1520 } 1521 DtInsertSubtable (ParentTable, Subtable); 1522 1523 /* 1524 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 1525 * should be taken to avoid accessing ACPI_TABLE_HADER fields. 1526 */ 1527 #if 0 1528 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM, 1529 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 1530 #endif 1531 /* Compile VTL */ 1532 1533 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0, 1534 &Subtable); 1535 if (ACPI_FAILURE (Status)) 1536 { 1537 return (Status); 1538 } 1539 1540 DtInsertSubtable (ParentTable, Subtable); 1541 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer); 1542 1543 DtPushSubtable (Subtable); 1544 ParentTable = DtPeekSubtable (); 1545 Count = 0; 1546 1547 while (*PFieldList) 1548 { 1549 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a, 1550 &Subtable); 1551 if (ACPI_FAILURE (Status)) 1552 { 1553 return (Status); 1554 } 1555 if (!Subtable) 1556 { 1557 break; 1558 } 1559 DtInsertSubtable (ParentTable, Subtable); 1560 Count++; 1561 } 1562 1563 DrtmVtl->ValidatedTableCount = Count; 1564 DtPopSubtable (); 1565 ParentTable = DtPeekSubtable (); 1566 1567 /* Compile RL */ 1568 1569 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1, 1570 &Subtable); 1571 if (ACPI_FAILURE (Status)) 1572 { 1573 return (Status); 1574 } 1575 1576 DtInsertSubtable (ParentTable, Subtable); 1577 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer); 1578 1579 DtPushSubtable (Subtable); 1580 ParentTable = DtPeekSubtable (); 1581 Count = 0; 1582 1583 while (*PFieldList) 1584 { 1585 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a, 1586 &Subtable); 1587 if (ACPI_FAILURE (Status)) 1588 { 1589 return (Status); 1590 } 1591 1592 if (!Subtable) 1593 { 1594 break; 1595 } 1596 1597 DtInsertSubtable (ParentTable, Subtable); 1598 Count++; 1599 } 1600 1601 DrtmRl->ResourceCount = Count; 1602 DtPopSubtable (); 1603 ParentTable = DtPeekSubtable (); 1604 1605 /* Compile DPS */ 1606 1607 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2, 1608 &Subtable); 1609 if (ACPI_FAILURE (Status)) 1610 { 1611 return (Status); 1612 } 1613 DtInsertSubtable (ParentTable, Subtable); 1614 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/ 1615 1616 1617 return (AE_OK); 1618 } 1619 1620 1621 /****************************************************************************** 1622 * 1623 * FUNCTION: DtCompileEinj 1624 * 1625 * PARAMETERS: List - Current field list pointer 1626 * 1627 * RETURN: Status 1628 * 1629 * DESCRIPTION: Compile EINJ. 1630 * 1631 *****************************************************************************/ 1632 1633 ACPI_STATUS 1634 DtCompileEinj ( 1635 void **List) 1636 { 1637 ACPI_STATUS Status; 1638 1639 1640 Status = DtCompileTwoSubtables (List, 1641 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0); 1642 return (Status); 1643 } 1644 1645 1646 /****************************************************************************** 1647 * 1648 * FUNCTION: DtCompileErdt 1649 * 1650 * PARAMETERS: List - Current field list pointer 1651 * 1652 * RETURN: Status 1653 * 1654 * DESCRIPTION: Compile ERST. Complex table with subtables and subsubtables. 1655 * 1656 *****************************************************************************/ 1657 1658 ACPI_STATUS 1659 DtCompileErdt ( 1660 void **List) 1661 { 1662 ACPI_STATUS Status; 1663 DT_SUBTABLE *Subtable, *RmddSubtable = NULL, *Subsubtable; 1664 DT_SUBTABLE *ParentTable; 1665 DT_FIELD **PFieldList = (DT_FIELD **) List; 1666 DT_FIELD *SubtableStart; 1667 ACPI_SUBTBL_HDR_16 *ErdtHeader; 1668 ACPI_DMTABLE_INFO *InfoTable; 1669 ACPI_ERDT_MMRC *Mmrc; 1670 ACPI_ERDT_IBRD *Ibrd; 1671 UINT32 NumEntries; 1672 BOOLEAN SeenRmdd = FALSE; 1673 BOOLEAN SeenSubtable = FALSE; 1674 1675 Status = DtCompileTable (PFieldList, AcpiDmTableInfoErdt, 1676 &Subtable); 1677 if (ACPI_FAILURE (Status)) 1678 { 1679 return (Status); 1680 } 1681 1682 ParentTable = DtPeekSubtable (); 1683 DtInsertSubtable (ParentTable, Subtable); 1684 1685 while (*PFieldList) 1686 { 1687 SubtableStart = *PFieldList; 1688 Status = DtCompileTable (PFieldList, AcpiDmTableInfoErdtHdr, 1689 &Subtable); 1690 if (ACPI_FAILURE (Status)) 1691 { 1692 return (Status); 1693 } 1694 1695 ErdtHeader = ACPI_CAST_PTR (ACPI_SUBTBL_HDR_16, Subtable->Buffer); 1696 1697 /* RMDD tables at top level. All others are subtables of preceeding RMDD */ 1698 if (ErdtHeader->Type == ACPI_ERDT_TYPE_RMDD) 1699 { 1700 if (SeenRmdd && SeenSubtable) 1701 DtPopSubtable (); 1702 SeenRmdd = TRUE; 1703 SeenSubtable = FALSE; 1704 RmddSubtable = Subtable; 1705 } 1706 else 1707 { 1708 if (!SeenSubtable) 1709 { 1710 DtPushSubtable (RmddSubtable); 1711 SeenSubtable = TRUE; 1712 } 1713 } 1714 1715 ParentTable = DtPeekSubtable (); 1716 DtInsertSubtable (ParentTable, Subtable); 1717 DtPushSubtable (Subtable); 1718 1719 switch (ErdtHeader->Type) 1720 { 1721 case ACPI_ERDT_TYPE_RMDD: 1722 InfoTable = AcpiDmTableInfoErdtRmdd; 1723 break; 1724 1725 case ACPI_ERDT_TYPE_CACD: 1726 InfoTable = AcpiDmTableInfoErdtCacd; 1727 break; 1728 1729 case ACPI_ERDT_TYPE_DACD: 1730 InfoTable = AcpiDmTableInfoErdtDacd; 1731 break; 1732 1733 case ACPI_ERDT_TYPE_CMRC: 1734 InfoTable = AcpiDmTableInfoErdtCmrc; 1735 break; 1736 1737 case ACPI_ERDT_TYPE_MMRC: 1738 InfoTable = AcpiDmTableInfoErdtMmrc; 1739 break; 1740 1741 case ACPI_ERDT_TYPE_MARC: 1742 InfoTable = AcpiDmTableInfoErdtMarc; 1743 break; 1744 1745 case ACPI_ERDT_TYPE_CARC: 1746 InfoTable = AcpiDmTableInfoErdtCarc; 1747 break; 1748 1749 case ACPI_ERDT_TYPE_CMRD: 1750 InfoTable = AcpiDmTableInfoErdtCmrd; 1751 break; 1752 1753 case ACPI_ERDT_TYPE_IBRD: 1754 InfoTable = AcpiDmTableInfoErdtIbrd; 1755 break; 1756 1757 case ACPI_ERDT_TYPE_IBAD: 1758 InfoTable = AcpiDmTableInfoErdtIbad; 1759 break; 1760 1761 case ACPI_ERDT_TYPE_CARD: 1762 InfoTable = AcpiDmTableInfoErdtCard; 1763 break; 1764 1765 default: 1766 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ERDT"); 1767 return (AE_ERROR); 1768 } 1769 1770 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1771 if (ACPI_FAILURE (Status)) 1772 { 1773 return (Status); 1774 } 1775 1776 ParentTable = DtPeekSubtable (); 1777 DtInsertSubtable (ParentTable, Subtable); 1778 1779 /* Some subtable types end with flex arrays */ 1780 1781 switch (ErdtHeader->Type) 1782 { 1783 case ACPI_ERDT_TYPE_CACD: 1784 while (*PFieldList) 1785 { 1786 Status = DtCompileTable (PFieldList, 1787 AcpiDmTableInfoErdtCacdX2apic, &Subtable); 1788 if (ACPI_FAILURE (Status)) 1789 { 1790 return (Status); 1791 } 1792 if (!Subtable) 1793 { 1794 break; 1795 } 1796 1797 ParentTable = DtPeekSubtable (); 1798 DtInsertSubtable (ParentTable, Subtable); 1799 } 1800 break; 1801 1802 case ACPI_ERDT_TYPE_DACD: 1803 while (*PFieldList) 1804 { 1805 Status = DtCompileTable (PFieldList, 1806 AcpiDmTableInfoErdtDacdScope, &Subtable); 1807 if (ACPI_FAILURE (Status)) 1808 { 1809 return (Status); 1810 } 1811 if (!Subtable) 1812 { 1813 break; 1814 } 1815 1816 DtPushSubtable (Subtable); 1817 while (*PFieldList) 1818 { 1819 Status = DtCompileTable (PFieldList, 1820 AcpiDmTableInfoErdtDacdPath, &Subsubtable); 1821 if (ACPI_FAILURE (Status)) 1822 { 1823 return (Status); 1824 } 1825 if (!Subsubtable) 1826 { 1827 break; 1828 } 1829 1830 ParentTable = DtPeekSubtable (); 1831 DtInsertSubtable (ParentTable, Subsubtable); 1832 } 1833 DtPopSubtable (); 1834 1835 ParentTable = DtPeekSubtable (); 1836 DtInsertSubtable (ParentTable, Subtable); 1837 } 1838 break; 1839 1840 case ACPI_ERDT_TYPE_MMRC: 1841 Mmrc = ACPI_SUB_PTR (ACPI_ERDT_MMRC, Subtable->Buffer, 1842 sizeof(ACPI_SUBTBL_HDR_16)); 1843 NumEntries = 0; 1844 while (*PFieldList) 1845 { 1846 Status = DtCompileTable (PFieldList, 1847 AcpiDmTableInfoErdtMmrcCorrFactor, &Subtable); 1848 if (ACPI_FAILURE (Status)) 1849 { 1850 return (Status); 1851 } 1852 if (!Subtable) 1853 { 1854 break; 1855 } 1856 1857 ParentTable = DtPeekSubtable (); 1858 DtInsertSubtable (ParentTable, Subtable); 1859 NumEntries++; 1860 } 1861 Mmrc->CorrFactorListLen = NumEntries; 1862 break; 1863 1864 case ACPI_ERDT_TYPE_IBRD: 1865 Ibrd = ACPI_SUB_PTR (ACPI_ERDT_IBRD, Subtable->Buffer, 1866 sizeof(ACPI_SUBTBL_HDR_16)); 1867 NumEntries = 0; 1868 while (*PFieldList) 1869 { 1870 Status = DtCompileTable (PFieldList, 1871 AcpiDmTableInfoErdtIbrdCorrFactor, &Subtable); 1872 if (ACPI_FAILURE (Status)) 1873 { 1874 return (Status); 1875 } 1876 if (!Subtable) 1877 { 1878 break; 1879 } 1880 1881 ParentTable = DtPeekSubtable (); 1882 DtInsertSubtable (ParentTable, Subtable); 1883 NumEntries++; 1884 } 1885 Ibrd->CorrFactorListLen = NumEntries; 1886 break; 1887 1888 default: 1889 /* Already checked for valid subtable type above */ 1890 1891 break; 1892 } 1893 DtPopSubtable (); 1894 } 1895 1896 if (SeenSubtable) 1897 { 1898 DtPopSubtable (); 1899 } 1900 1901 return (AE_OK); 1902 } 1903 1904 1905 /****************************************************************************** 1906 * 1907 * FUNCTION: DtCompileErst 1908 * 1909 * PARAMETERS: List - Current field list pointer 1910 * 1911 * RETURN: Status 1912 * 1913 * DESCRIPTION: Compile ERST. 1914 * 1915 *****************************************************************************/ 1916 1917 ACPI_STATUS 1918 DtCompileErst ( 1919 void **List) 1920 { 1921 ACPI_STATUS Status; 1922 1923 1924 Status = DtCompileTwoSubtables (List, 1925 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0); 1926 return (Status); 1927 } 1928 1929 1930 /****************************************************************************** 1931 * 1932 * FUNCTION: DtCompileGtdt 1933 * 1934 * PARAMETERS: List - Current field list pointer 1935 * 1936 * RETURN: Status 1937 * 1938 * DESCRIPTION: Compile GTDT. 1939 * 1940 *****************************************************************************/ 1941 1942 ACPI_STATUS 1943 DtCompileGtdt ( 1944 void **List) 1945 { 1946 ACPI_STATUS Status; 1947 DT_SUBTABLE *Subtable; 1948 DT_SUBTABLE *ParentTable; 1949 DT_FIELD **PFieldList = (DT_FIELD **) List; 1950 DT_FIELD *SubtableStart; 1951 ACPI_SUBTABLE_HEADER *GtdtHeader; 1952 ACPI_DMTABLE_INFO *InfoTable; 1953 UINT32 GtCount; 1954 ACPI_TABLE_HEADER *Header; 1955 1956 1957 ParentTable = DtPeekSubtable (); 1958 1959 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 1960 1961 /* Compile the main table */ 1962 1963 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt, 1964 &Subtable); 1965 if (ACPI_FAILURE (Status)) 1966 { 1967 return (Status); 1968 } 1969 1970 /* GTDT revision 3 later contains 2 extra fields before subtables */ 1971 1972 if (Header->Revision > 2) 1973 { 1974 ParentTable = DtPeekSubtable (); 1975 DtInsertSubtable (ParentTable, Subtable); 1976 1977 Status = DtCompileTable (PFieldList, 1978 AcpiDmTableInfoGtdtEl2, &Subtable); 1979 if (ACPI_FAILURE (Status)) 1980 { 1981 return (Status); 1982 } 1983 } 1984 1985 ParentTable = DtPeekSubtable (); 1986 DtInsertSubtable (ParentTable, Subtable); 1987 1988 while (*PFieldList) 1989 { 1990 SubtableStart = *PFieldList; 1991 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr, 1992 &Subtable); 1993 if (ACPI_FAILURE (Status)) 1994 { 1995 return (Status); 1996 } 1997 1998 ParentTable = DtPeekSubtable (); 1999 DtInsertSubtable (ParentTable, Subtable); 2000 DtPushSubtable (Subtable); 2001 2002 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer); 2003 2004 switch (GtdtHeader->Type) 2005 { 2006 case ACPI_GTDT_TYPE_TIMER_BLOCK: 2007 2008 InfoTable = AcpiDmTableInfoGtdt0; 2009 break; 2010 2011 case ACPI_GTDT_TYPE_WATCHDOG: 2012 2013 InfoTable = AcpiDmTableInfoGtdt1; 2014 break; 2015 2016 default: 2017 2018 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT"); 2019 return (AE_ERROR); 2020 } 2021 2022 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 2023 if (ACPI_FAILURE (Status)) 2024 { 2025 return (Status); 2026 } 2027 2028 ParentTable = DtPeekSubtable (); 2029 DtInsertSubtable (ParentTable, Subtable); 2030 2031 /* 2032 * Additional GT block subtable data 2033 */ 2034 2035 switch (GtdtHeader->Type) 2036 { 2037 case ACPI_GTDT_TYPE_TIMER_BLOCK: 2038 2039 DtPushSubtable (Subtable); 2040 ParentTable = DtPeekSubtable (); 2041 2042 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK, 2043 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount; 2044 2045 while (GtCount) 2046 { 2047 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a, 2048 &Subtable); 2049 if (ACPI_FAILURE (Status)) 2050 { 2051 return (Status); 2052 } 2053 2054 DtInsertSubtable (ParentTable, Subtable); 2055 GtCount--; 2056 } 2057 2058 DtPopSubtable (); 2059 break; 2060 2061 default: 2062 2063 break; 2064 } 2065 2066 DtPopSubtable (); 2067 } 2068 2069 return (AE_OK); 2070 } 2071 2072 2073 /****************************************************************************** 2074 * 2075 * FUNCTION: DtCompileFpdt 2076 * 2077 * PARAMETERS: List - Current field list pointer 2078 * 2079 * RETURN: Status 2080 * 2081 * DESCRIPTION: Compile FPDT. 2082 * 2083 *****************************************************************************/ 2084 2085 ACPI_STATUS 2086 DtCompileFpdt ( 2087 void **List) 2088 { 2089 ACPI_STATUS Status; 2090 ACPI_FPDT_HEADER *FpdtHeader; 2091 DT_SUBTABLE *Subtable; 2092 DT_SUBTABLE *ParentTable; 2093 ACPI_DMTABLE_INFO *InfoTable; 2094 DT_FIELD **PFieldList = (DT_FIELD **) List; 2095 DT_FIELD *SubtableStart; 2096 2097 2098 while (*PFieldList) 2099 { 2100 SubtableStart = *PFieldList; 2101 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr, 2102 &Subtable); 2103 if (ACPI_FAILURE (Status)) 2104 { 2105 return (Status); 2106 } 2107 2108 ParentTable = DtPeekSubtable (); 2109 DtInsertSubtable (ParentTable, Subtable); 2110 DtPushSubtable (Subtable); 2111 2112 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer); 2113 2114 switch (FpdtHeader->Type) 2115 { 2116 case ACPI_FPDT_TYPE_BOOT: 2117 2118 InfoTable = AcpiDmTableInfoFpdt0; 2119 break; 2120 2121 case ACPI_FPDT_TYPE_S3PERF: 2122 2123 InfoTable = AcpiDmTableInfoFpdt1; 2124 break; 2125 2126 default: 2127 2128 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT"); 2129 return (AE_ERROR); 2130 break; 2131 } 2132 2133 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 2134 if (ACPI_FAILURE (Status)) 2135 { 2136 return (Status); 2137 } 2138 2139 ParentTable = DtPeekSubtable (); 2140 DtInsertSubtable (ParentTable, Subtable); 2141 DtPopSubtable (); 2142 } 2143 2144 return (AE_OK); 2145 } 2146 2147 2148 /****************************************************************************** 2149 * 2150 * FUNCTION: DtCompileHest 2151 * 2152 * PARAMETERS: List - Current field list pointer 2153 * 2154 * RETURN: Status 2155 * 2156 * DESCRIPTION: Compile HEST. 2157 * 2158 *****************************************************************************/ 2159 2160 ACPI_STATUS 2161 DtCompileHest ( 2162 void **List) 2163 { 2164 ACPI_STATUS Status; 2165 DT_SUBTABLE *Subtable; 2166 DT_SUBTABLE *ParentTable; 2167 DT_FIELD **PFieldList = (DT_FIELD **) List; 2168 DT_FIELD *SubtableStart; 2169 ACPI_DMTABLE_INFO *InfoTable; 2170 UINT16 Type; 2171 UINT32 BankCount; 2172 2173 2174 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest, 2175 &Subtable); 2176 if (ACPI_FAILURE (Status)) 2177 { 2178 return (Status); 2179 } 2180 2181 ParentTable = DtPeekSubtable (); 2182 DtInsertSubtable (ParentTable, Subtable); 2183 2184 while (*PFieldList) 2185 { 2186 /* Get subtable type */ 2187 2188 SubtableStart = *PFieldList; 2189 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0); 2190 2191 switch (Type) 2192 { 2193 case ACPI_HEST_TYPE_IA32_CHECK: 2194 2195 InfoTable = AcpiDmTableInfoHest0; 2196 break; 2197 2198 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 2199 2200 InfoTable = AcpiDmTableInfoHest1; 2201 break; 2202 2203 case ACPI_HEST_TYPE_IA32_NMI: 2204 2205 InfoTable = AcpiDmTableInfoHest2; 2206 break; 2207 2208 case ACPI_HEST_TYPE_AER_ROOT_PORT: 2209 2210 InfoTable = AcpiDmTableInfoHest6; 2211 break; 2212 2213 case ACPI_HEST_TYPE_AER_ENDPOINT: 2214 2215 InfoTable = AcpiDmTableInfoHest7; 2216 break; 2217 2218 case ACPI_HEST_TYPE_AER_BRIDGE: 2219 2220 InfoTable = AcpiDmTableInfoHest8; 2221 break; 2222 2223 case ACPI_HEST_TYPE_GENERIC_ERROR: 2224 2225 InfoTable = AcpiDmTableInfoHest9; 2226 break; 2227 2228 case ACPI_HEST_TYPE_GENERIC_ERROR_V2: 2229 2230 InfoTable = AcpiDmTableInfoHest10; 2231 break; 2232 2233 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 2234 2235 InfoTable = AcpiDmTableInfoHest11; 2236 break; 2237 2238 default: 2239 2240 /* Cannot continue on unknown type */ 2241 2242 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST"); 2243 return (AE_ERROR); 2244 } 2245 2246 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 2247 if (ACPI_FAILURE (Status)) 2248 { 2249 return (Status); 2250 } 2251 2252 DtInsertSubtable (ParentTable, Subtable); 2253 2254 /* 2255 * Additional subtable data - IA32 Error Bank(s) 2256 */ 2257 BankCount = 0; 2258 switch (Type) 2259 { 2260 case ACPI_HEST_TYPE_IA32_CHECK: 2261 2262 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK, 2263 Subtable->Buffer))->NumHardwareBanks; 2264 break; 2265 2266 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 2267 2268 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED, 2269 Subtable->Buffer))->NumHardwareBanks; 2270 break; 2271 2272 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 2273 2274 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK, 2275 Subtable->Buffer))->NumHardwareBanks; 2276 break; 2277 2278 default: 2279 2280 break; 2281 } 2282 2283 while (BankCount) 2284 { 2285 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank, 2286 &Subtable); 2287 if (ACPI_FAILURE (Status)) 2288 { 2289 return (Status); 2290 } 2291 2292 DtInsertSubtable (ParentTable, Subtable); 2293 BankCount--; 2294 } 2295 } 2296 2297 return (AE_OK); 2298 } 2299 2300 2301 /****************************************************************************** 2302 * 2303 * FUNCTION: DtCompileHmat 2304 * 2305 * PARAMETERS: List - Current field list pointer 2306 * 2307 * RETURN: Status 2308 * 2309 * DESCRIPTION: Compile HMAT. 2310 * 2311 *****************************************************************************/ 2312 2313 ACPI_STATUS 2314 DtCompileHmat ( 2315 void **List) 2316 { 2317 ACPI_STATUS Status; 2318 DT_SUBTABLE *Subtable; 2319 DT_SUBTABLE *ParentTable; 2320 DT_FIELD **PFieldList = (DT_FIELD **) List; 2321 DT_FIELD *SubtableStart; 2322 DT_FIELD *EntryStart; 2323 ACPI_HMAT_STRUCTURE *HmatStruct; 2324 ACPI_HMAT_LOCALITY *HmatLocality; 2325 ACPI_HMAT_CACHE *HmatCache; 2326 ACPI_DMTABLE_INFO *InfoTable; 2327 UINT32 IntPDNumber; 2328 UINT32 TgtPDNumber; 2329 UINT64 EntryNumber; 2330 UINT16 SMBIOSHandleNumber; 2331 2332 2333 ParentTable = DtPeekSubtable (); 2334 2335 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat, 2336 &Subtable); 2337 if (ACPI_FAILURE (Status)) 2338 { 2339 return (Status); 2340 } 2341 DtInsertSubtable (ParentTable, Subtable); 2342 2343 while (*PFieldList) 2344 { 2345 /* Compile HMAT structure header */ 2346 2347 SubtableStart = *PFieldList; 2348 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr, 2349 &Subtable); 2350 if (ACPI_FAILURE (Status)) 2351 { 2352 return (Status); 2353 } 2354 DtInsertSubtable (ParentTable, Subtable); 2355 2356 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer); 2357 HmatStruct->Length = Subtable->Length; 2358 2359 /* Compile HMAT structure body */ 2360 2361 switch (HmatStruct->Type) 2362 { 2363 case ACPI_HMAT_TYPE_ADDRESS_RANGE: 2364 2365 InfoTable = AcpiDmTableInfoHmat0; 2366 break; 2367 2368 case ACPI_HMAT_TYPE_LOCALITY: 2369 2370 InfoTable = AcpiDmTableInfoHmat1; 2371 break; 2372 2373 case ACPI_HMAT_TYPE_CACHE: 2374 2375 InfoTable = AcpiDmTableInfoHmat2; 2376 break; 2377 2378 default: 2379 2380 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT"); 2381 return (AE_ERROR); 2382 } 2383 2384 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 2385 if (ACPI_FAILURE (Status)) 2386 { 2387 return (Status); 2388 } 2389 DtInsertSubtable (ParentTable, Subtable); 2390 HmatStruct->Length += Subtable->Length; 2391 2392 /* Compile HMAT structure additional */ 2393 2394 switch (HmatStruct->Type) 2395 { 2396 case ACPI_HMAT_TYPE_LOCALITY: 2397 2398 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY, 2399 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 2400 2401 /* Compile initiator proximity domain list */ 2402 2403 IntPDNumber = 0; 2404 while (*PFieldList) 2405 { 2406 Status = DtCompileTable (PFieldList, 2407 AcpiDmTableInfoHmat1a, &Subtable); 2408 if (ACPI_FAILURE (Status)) 2409 { 2410 return (Status); 2411 } 2412 if (!Subtable) 2413 { 2414 break; 2415 } 2416 DtInsertSubtable (ParentTable, Subtable); 2417 HmatStruct->Length += Subtable->Length; 2418 IntPDNumber++; 2419 } 2420 HmatLocality->NumberOfInitiatorPDs = IntPDNumber; 2421 2422 /* Compile target proximity domain list */ 2423 2424 TgtPDNumber = 0; 2425 while (*PFieldList) 2426 { 2427 Status = DtCompileTable (PFieldList, 2428 AcpiDmTableInfoHmat1b, &Subtable); 2429 if (ACPI_FAILURE (Status)) 2430 { 2431 return (Status); 2432 } 2433 if (!Subtable) 2434 { 2435 break; 2436 } 2437 DtInsertSubtable (ParentTable, Subtable); 2438 HmatStruct->Length += Subtable->Length; 2439 TgtPDNumber++; 2440 } 2441 HmatLocality->NumberOfTargetPDs = TgtPDNumber; 2442 2443 /* Save start of the entries for reporting errors */ 2444 2445 EntryStart = *PFieldList; 2446 2447 /* Compile latency/bandwidth entries */ 2448 2449 EntryNumber = 0; 2450 while (*PFieldList) 2451 { 2452 Status = DtCompileTable (PFieldList, 2453 AcpiDmTableInfoHmat1c, &Subtable); 2454 if (ACPI_FAILURE (Status)) 2455 { 2456 return (Status); 2457 } 2458 if (!Subtable) 2459 { 2460 break; 2461 } 2462 DtInsertSubtable (ParentTable, Subtable); 2463 HmatStruct->Length += Subtable->Length; 2464 EntryNumber++; 2465 } 2466 2467 /* Validate number of entries */ 2468 2469 if (EntryNumber != 2470 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber)) 2471 { 2472 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT"); 2473 return (AE_ERROR); 2474 } 2475 break; 2476 2477 case ACPI_HMAT_TYPE_CACHE: 2478 2479 /* Compile SMBIOS handles */ 2480 2481 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE, 2482 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 2483 SMBIOSHandleNumber = 0; 2484 while (*PFieldList) 2485 { 2486 Status = DtCompileTable (PFieldList, 2487 AcpiDmTableInfoHmat2a, &Subtable); 2488 if (ACPI_FAILURE (Status)) 2489 { 2490 return (Status); 2491 } 2492 if (!Subtable) 2493 { 2494 break; 2495 } 2496 DtInsertSubtable (ParentTable, Subtable); 2497 HmatStruct->Length += Subtable->Length; 2498 SMBIOSHandleNumber++; 2499 } 2500 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber; 2501 break; 2502 2503 default: 2504 2505 break; 2506 } 2507 } 2508 2509 return (AE_OK); 2510 } 2511 2512 2513 /****************************************************************************** 2514 * 2515 * FUNCTION: DtCompileIort 2516 * 2517 * PARAMETERS: List - Current field list pointer 2518 * 2519 * RETURN: Status 2520 * 2521 * DESCRIPTION: Compile IORT. 2522 * 2523 *****************************************************************************/ 2524 2525 ACPI_STATUS 2526 DtCompileIort ( 2527 void **List) 2528 { 2529 ACPI_STATUS Status; 2530 DT_SUBTABLE *Subtable; 2531 DT_SUBTABLE *ParentTable; 2532 DT_FIELD **PFieldList = (DT_FIELD **) List; 2533 DT_FIELD *SubtableStart; 2534 ACPI_TABLE_HEADER *Table; 2535 ACPI_TABLE_IORT *Iort; 2536 ACPI_IORT_NODE *IortNode; 2537 ACPI_IORT_ITS_GROUP *IortItsGroup; 2538 ACPI_IORT_SMMU *IortSmmu; 2539 ACPI_IORT_RMR *IortRmr; 2540 UINT32 NodeNumber; 2541 UINT32 NodeLength; 2542 UINT32 IdMappingNumber; 2543 UINT32 ItsNumber; 2544 UINT32 ContextIrptNumber; 2545 UINT32 PmuIrptNumber; 2546 UINT32 PaddingLength; 2547 UINT8 Revision; 2548 UINT32 RmrCount; 2549 2550 2551 ParentTable = DtPeekSubtable (); 2552 2553 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort, 2554 &Subtable); 2555 if (ACPI_FAILURE (Status)) 2556 { 2557 return (Status); 2558 } 2559 DtInsertSubtable (ParentTable, Subtable); 2560 2561 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 2562 Revision = Table->Revision; 2563 2564 /* IORT Revisions E, E.a & E.c have known issues and are not supported */ 2565 2566 if (Revision == 1 || Revision == 2 || Revision == 4) 2567 { 2568 DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision"); 2569 return (AE_ERROR); 2570 } 2571 2572 /* 2573 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 2574 * should be taken to avoid accessing ACPI_TABLE_HEADER fields. 2575 */ 2576 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT, 2577 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 2578 2579 /* 2580 * OptionalPadding - Variable-length data 2581 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT)) 2582 * Optionally allows the generic data types to be used for filling 2583 * this field. 2584 */ 2585 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT); 2586 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad, 2587 &Subtable); 2588 if (ACPI_FAILURE (Status)) 2589 { 2590 return (Status); 2591 } 2592 if (Subtable) 2593 { 2594 DtInsertSubtable (ParentTable, Subtable); 2595 Iort->NodeOffset += Subtable->Length; 2596 } 2597 else 2598 { 2599 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList), 2600 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength); 2601 if (ACPI_FAILURE (Status)) 2602 { 2603 return (Status); 2604 } 2605 Iort->NodeOffset += PaddingLength; 2606 } 2607 2608 NodeNumber = 0; 2609 while (*PFieldList) 2610 { 2611 SubtableStart = *PFieldList; 2612 if (Revision == 0) 2613 { 2614 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr, 2615 &Subtable); 2616 } 2617 else if (Revision >= 3) 2618 { 2619 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3, 2620 &Subtable); 2621 } 2622 2623 if (ACPI_FAILURE (Status)) 2624 { 2625 return (Status); 2626 } 2627 2628 DtInsertSubtable (ParentTable, Subtable); 2629 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer); 2630 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData); 2631 2632 DtPushSubtable (Subtable); 2633 ParentTable = DtPeekSubtable (); 2634 2635 switch (IortNode->Type) 2636 { 2637 case ACPI_IORT_NODE_ITS_GROUP: 2638 2639 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0, 2640 &Subtable); 2641 if (ACPI_FAILURE (Status)) 2642 { 2643 return (Status); 2644 } 2645 2646 DtInsertSubtable (ParentTable, Subtable); 2647 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer); 2648 NodeLength += Subtable->Length; 2649 2650 ItsNumber = 0; 2651 while (*PFieldList) 2652 { 2653 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a, 2654 &Subtable); 2655 if (ACPI_FAILURE (Status)) 2656 { 2657 return (Status); 2658 } 2659 if (!Subtable) 2660 { 2661 break; 2662 } 2663 2664 DtInsertSubtable (ParentTable, Subtable); 2665 NodeLength += Subtable->Length; 2666 ItsNumber++; 2667 } 2668 2669 IortItsGroup->ItsCount = ItsNumber; 2670 break; 2671 2672 case ACPI_IORT_NODE_NAMED_COMPONENT: 2673 2674 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1, 2675 &Subtable); 2676 if (ACPI_FAILURE (Status)) 2677 { 2678 return (Status); 2679 } 2680 2681 DtInsertSubtable (ParentTable, Subtable); 2682 NodeLength += Subtable->Length; 2683 2684 /* 2685 * Padding - Variable-length data 2686 * Optionally allows the offset of the ID mappings to be used 2687 * for filling this field. 2688 */ 2689 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a, 2690 &Subtable); 2691 if (ACPI_FAILURE (Status)) 2692 { 2693 return (Status); 2694 } 2695 2696 if (Subtable) 2697 { 2698 DtInsertSubtable (ParentTable, Subtable); 2699 NodeLength += Subtable->Length; 2700 } 2701 else 2702 { 2703 if (NodeLength > IortNode->MappingOffset) 2704 { 2705 return (AE_BAD_DATA); 2706 } 2707 2708 if (NodeLength < IortNode->MappingOffset) 2709 { 2710 Status = DtCompilePadding ( 2711 IortNode->MappingOffset - NodeLength, 2712 &Subtable); 2713 if (ACPI_FAILURE (Status)) 2714 { 2715 return (Status); 2716 } 2717 2718 DtInsertSubtable (ParentTable, Subtable); 2719 NodeLength = IortNode->MappingOffset; 2720 } 2721 } 2722 break; 2723 2724 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX: 2725 2726 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2, 2727 &Subtable); 2728 if (ACPI_FAILURE (Status)) 2729 { 2730 return (Status); 2731 } 2732 2733 DtInsertSubtable (ParentTable, Subtable); 2734 NodeLength += Subtable->Length; 2735 break; 2736 2737 case ACPI_IORT_NODE_SMMU: 2738 2739 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3, 2740 &Subtable); 2741 if (ACPI_FAILURE (Status)) 2742 { 2743 return (Status); 2744 } 2745 2746 DtInsertSubtable (ParentTable, Subtable); 2747 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer); 2748 NodeLength += Subtable->Length; 2749 2750 /* Compile global interrupt array */ 2751 2752 IortSmmu->GlobalInterruptOffset = NodeLength; 2753 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a, 2754 &Subtable); 2755 if (ACPI_FAILURE (Status)) 2756 { 2757 return (Status); 2758 } 2759 2760 DtInsertSubtable (ParentTable, Subtable); 2761 NodeLength += Subtable->Length; 2762 2763 /* Compile context interrupt array */ 2764 2765 ContextIrptNumber = 0; 2766 IortSmmu->ContextInterruptOffset = NodeLength; 2767 while (*PFieldList) 2768 { 2769 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b, 2770 &Subtable); 2771 if (ACPI_FAILURE (Status)) 2772 { 2773 return (Status); 2774 } 2775 2776 if (!Subtable) 2777 { 2778 break; 2779 } 2780 2781 DtInsertSubtable (ParentTable, Subtable); 2782 NodeLength += Subtable->Length; 2783 ContextIrptNumber++; 2784 } 2785 2786 IortSmmu->ContextInterruptCount = ContextIrptNumber; 2787 2788 /* Compile PMU interrupt array */ 2789 2790 PmuIrptNumber = 0; 2791 IortSmmu->PmuInterruptOffset = NodeLength; 2792 while (*PFieldList) 2793 { 2794 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c, 2795 &Subtable); 2796 if (ACPI_FAILURE (Status)) 2797 { 2798 return (Status); 2799 } 2800 2801 if (!Subtable) 2802 { 2803 break; 2804 } 2805 2806 DtInsertSubtable (ParentTable, Subtable); 2807 NodeLength += Subtable->Length; 2808 PmuIrptNumber++; 2809 } 2810 2811 IortSmmu->PmuInterruptCount = PmuIrptNumber; 2812 break; 2813 2814 case ACPI_IORT_NODE_SMMU_V3: 2815 2816 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4, 2817 &Subtable); 2818 if (ACPI_FAILURE (Status)) 2819 { 2820 return (Status); 2821 } 2822 2823 DtInsertSubtable (ParentTable, Subtable); 2824 NodeLength += Subtable->Length; 2825 break; 2826 2827 case ACPI_IORT_NODE_PMCG: 2828 2829 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5, 2830 &Subtable); 2831 if (ACPI_FAILURE (Status)) 2832 { 2833 return (Status); 2834 } 2835 2836 DtInsertSubtable (ParentTable, Subtable); 2837 NodeLength += Subtable->Length; 2838 break; 2839 2840 case ACPI_IORT_NODE_RMR: 2841 2842 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6, 2843 &Subtable); 2844 if (ACPI_FAILURE (Status)) 2845 { 2846 return (Status); 2847 } 2848 2849 DtInsertSubtable (ParentTable, Subtable); 2850 IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer); 2851 NodeLength += Subtable->Length; 2852 2853 /* Compile RMR Descriptors */ 2854 2855 RmrCount = 0; 2856 IortRmr->RmrOffset = NodeLength; 2857 while (*PFieldList) 2858 { 2859 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a, 2860 &Subtable); 2861 if (ACPI_FAILURE (Status)) 2862 { 2863 return (Status); 2864 } 2865 2866 if (!Subtable) 2867 { 2868 break; 2869 } 2870 2871 DtInsertSubtable (ParentTable, Subtable); 2872 NodeLength += sizeof (ACPI_IORT_RMR_DESC); 2873 RmrCount++; 2874 } 2875 2876 IortRmr->RmrCount = RmrCount; 2877 break; 2878 2879 default: 2880 2881 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT"); 2882 return (AE_ERROR); 2883 } 2884 2885 /* Compile Array of ID mappings */ 2886 2887 IortNode->MappingOffset = NodeLength; 2888 IdMappingNumber = 0; 2889 while (*PFieldList) 2890 { 2891 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap, 2892 &Subtable); 2893 if (ACPI_FAILURE (Status)) 2894 { 2895 return (Status); 2896 } 2897 2898 if (!Subtable) 2899 { 2900 break; 2901 } 2902 2903 DtInsertSubtable (ParentTable, Subtable); 2904 NodeLength += sizeof (ACPI_IORT_ID_MAPPING); 2905 IdMappingNumber++; 2906 } 2907 2908 IortNode->MappingCount = IdMappingNumber; 2909 if (!IdMappingNumber) 2910 { 2911 IortNode->MappingOffset = 0; 2912 } 2913 2914 /* 2915 * Node length can be determined by DT_LENGTH option 2916 * IortNode->Length = NodeLength; 2917 */ 2918 DtPopSubtable (); 2919 ParentTable = DtPeekSubtable (); 2920 NodeNumber++; 2921 } 2922 2923 Iort->NodeCount = NodeNumber; 2924 return (AE_OK); 2925 } 2926 2927 2928 /****************************************************************************** 2929 * 2930 * FUNCTION: DtCompileIovt 2931 * 2932 * PARAMETERS: List - Current field list pointer 2933 * 2934 * RETURN: Status 2935 * 2936 * DESCRIPTION: Compile Iovt. Notes: 2937 * The IOVT is essentially a flat table, with the following 2938 * structure: 2939 * <Main ACPI Table Header> 2940 * <Main subtable - virtualization info> 2941 * <IOVT> 2942 * <Device Entries> 2943 * ... 2944 * <IOVT> 2945 * <IOVT> 2946 * ... 2947 * 2948 *****************************************************************************/ 2949 2950 ACPI_STATUS 2951 DtCompileIovt ( 2952 void **List) 2953 { 2954 ACPI_STATUS Status; 2955 DT_SUBTABLE *Subtable; 2956 DT_SUBTABLE *ParentTable; 2957 DT_FIELD **PFieldList = (DT_FIELD **) List; 2958 ACPI_TABLE_IOVT *Iovt; 2959 UINT16 IommuCount; 2960 ACPI_IOVT_IOMMU *Iommu; 2961 UINT32 DeviceEntryNum; 2962 2963 2964 ParentTable = DtPeekSubtable (); 2965 /* Main table */ 2966 2967 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovt, 2968 &Subtable); 2969 if (ACPI_FAILURE (Status)) 2970 { 2971 return (Status); 2972 } 2973 2974 DtInsertSubtable (ParentTable, Subtable); 2975 DtPushSubtable (Subtable); 2976 2977 Iovt = ACPI_SUB_PTR (ACPI_TABLE_IOVT, Subtable->Buffer, 2978 sizeof (ACPI_TABLE_HEADER)); 2979 2980 for (IommuCount = 0; IommuCount < Iovt->IommuCount; IommuCount++) 2981 { 2982 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovt0, 2983 &Subtable); 2984 if (ACPI_FAILURE (Status)) 2985 { 2986 return (Status); 2987 } 2988 2989 ParentTable = DtPeekSubtable (); 2990 DtInsertSubtable (ParentTable, Subtable); 2991 DtPushSubtable (Subtable); 2992 2993 Iommu = ACPI_CAST_PTR(ACPI_IOVT_IOMMU, Subtable->Buffer); 2994 for (DeviceEntryNum = 0; DeviceEntryNum < Iommu->DeviceEntryNum; DeviceEntryNum++) 2995 { 2996 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovtdev, 2997 &Subtable); 2998 if (ACPI_FAILURE (Status)) 2999 { 3000 return (Status); 3001 } 3002 3003 ParentTable = DtPeekSubtable (); 3004 DtInsertSubtable (ParentTable, Subtable); 3005 } 3006 DtPopSubtable(); 3007 } 3008 3009 return (AE_OK); 3010 } 3011 3012 3013 /****************************************************************************** 3014 * 3015 * FUNCTION: DtCompileIvrs 3016 * 3017 * PARAMETERS: List - Current field list pointer 3018 * 3019 * RETURN: Status 3020 * 3021 * DESCRIPTION: Compile IVRS. Notes: 3022 * The IVRS is essentially a flat table, with the following 3023 * structure: 3024 * <Main ACPI Table Header> 3025 * <Main subtable - virtualization info> 3026 * <IVHD> 3027 * <Device Entries> 3028 * ... 3029 * <IVHD> 3030 * <Device Entries> 3031 * <IVMD> 3032 * ... 3033 * 3034 *****************************************************************************/ 3035 3036 ACPI_STATUS 3037 DtCompileIvrs ( 3038 void **List) 3039 { 3040 ACPI_STATUS Status; 3041 DT_SUBTABLE *Subtable; 3042 DT_SUBTABLE *ParentTable; 3043 DT_SUBTABLE *MainSubtable; 3044 DT_FIELD **PFieldList = (DT_FIELD **) List; 3045 DT_FIELD *SubtableStart; 3046 ACPI_DMTABLE_INFO *InfoTable = NULL; 3047 UINT8 SubtableType; 3048 UINT8 Temp64[16]; 3049 UINT8 Temp8; 3050 3051 3052 /* Main table */ 3053 3054 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs, 3055 &Subtable); 3056 if (ACPI_FAILURE (Status)) 3057 { 3058 return (Status); 3059 } 3060 3061 ParentTable = DtPeekSubtable (); 3062 DtInsertSubtable (ParentTable, Subtable); 3063 DtPushSubtable (Subtable); 3064 3065 /* Save a pointer to the main subtable */ 3066 3067 MainSubtable = Subtable; 3068 3069 while (*PFieldList) 3070 { 3071 SubtableStart = *PFieldList; 3072 3073 /* Compile the SubtableType integer */ 3074 3075 DtCompileInteger (&SubtableType, *PFieldList, 1, 0); 3076 3077 switch (SubtableType) 3078 { 3079 3080 /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */ 3081 3082 case ACPI_IVRS_TYPE_HARDWARE1: 3083 3084 InfoTable = AcpiDmTableInfoIvrsHware1; 3085 break; 3086 3087 /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */ 3088 3089 case ACPI_IVRS_TYPE_HARDWARE2: 3090 case ACPI_IVRS_TYPE_HARDWARE3: 3091 3092 InfoTable = AcpiDmTableInfoIvrsHware23; 3093 break; 3094 3095 /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */ 3096 3097 case ACPI_IVRS_TYPE_MEMORY1: 3098 case ACPI_IVRS_TYPE_MEMORY2: 3099 case ACPI_IVRS_TYPE_MEMORY3: 3100 3101 InfoTable = AcpiDmTableInfoIvrsMemory; 3102 break; 3103 3104 /* 4-byte device entries */ 3105 3106 case ACPI_IVRS_TYPE_PAD4: 3107 case ACPI_IVRS_TYPE_ALL: 3108 case ACPI_IVRS_TYPE_SELECT: 3109 case ACPI_IVRS_TYPE_START: 3110 case ACPI_IVRS_TYPE_END: 3111 3112 InfoTable = AcpiDmTableInfoIvrs4; 3113 break; 3114 3115 /* 8-byte device entries, type A */ 3116 3117 case ACPI_IVRS_TYPE_ALIAS_SELECT: 3118 case ACPI_IVRS_TYPE_ALIAS_START: 3119 3120 InfoTable = AcpiDmTableInfoIvrs8a; 3121 break; 3122 3123 /* 8-byte device entries, type B */ 3124 3125 case ACPI_IVRS_TYPE_EXT_SELECT: 3126 case ACPI_IVRS_TYPE_EXT_START: 3127 3128 InfoTable = AcpiDmTableInfoIvrs8b; 3129 break; 3130 3131 /* 8-byte device entries, type C */ 3132 3133 case ACPI_IVRS_TYPE_SPECIAL: 3134 3135 InfoTable = AcpiDmTableInfoIvrs8c; 3136 break; 3137 3138 /* Variable device entries, type F0h */ 3139 3140 case ACPI_IVRS_TYPE_HID: 3141 3142 InfoTable = AcpiDmTableInfoIvrsHid; 3143 break; 3144 3145 default: 3146 3147 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, 3148 "IVRS Device Entry"); 3149 return (AE_ERROR); 3150 } 3151 3152 /* Compile the InfoTable from above */ 3153 3154 Status = DtCompileTable (PFieldList, InfoTable, 3155 &Subtable); 3156 if (ACPI_FAILURE (Status)) 3157 { 3158 return (Status); 3159 } 3160 3161 ParentTable = DtPeekSubtable (); 3162 if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 && 3163 SubtableType != ACPI_IVRS_TYPE_HARDWARE2 && 3164 SubtableType != ACPI_IVRS_TYPE_HARDWARE3 && 3165 SubtableType != ACPI_IVRS_TYPE_HID && 3166 SubtableType != ACPI_IVRS_TYPE_MEMORY1 && 3167 SubtableType != ACPI_IVRS_TYPE_MEMORY2 && 3168 SubtableType != ACPI_IVRS_TYPE_MEMORY3) 3169 { 3170 if (ParentTable) 3171 DtInsertSubtable (ParentTable, Subtable); 3172 } 3173 3174 switch (SubtableType) 3175 { 3176 case ACPI_IVRS_TYPE_HARDWARE1: 3177 case ACPI_IVRS_TYPE_HARDWARE2: 3178 case ACPI_IVRS_TYPE_HARDWARE3: 3179 case ACPI_IVRS_TYPE_MEMORY1: 3180 case ACPI_IVRS_TYPE_MEMORY2: 3181 case ACPI_IVRS_TYPE_MEMORY3: 3182 3183 /* Insert these IVHDs/IVMDs at the root subtable */ 3184 3185 DtInsertSubtable (MainSubtable, Subtable); 3186 DtPushSubtable (Subtable); 3187 break; 3188 3189 case ACPI_IVRS_TYPE_HID: 3190 3191 /* Special handling for the HID named device entry (0xF0) */ 3192 3193 if (ParentTable) 3194 { 3195 DtInsertSubtable (ParentTable, Subtable); 3196 } 3197 3198 /* 3199 * Process the HID value. First, get the HID value as a string. 3200 */ 3201 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); 3202 3203 /* 3204 * Determine if the HID is an integer or a string. 3205 * An integer is defined to be 32 bits, with the upper 32 bits 3206 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit 3207 * integer or a character string. If an integer, the lower 3208 * 4 bytes of the field contain the integer and the upper 3209 * 4 bytes are padded with 0". 3210 */ 3211 if (UtIsIdInteger ((UINT8 *) &Temp64)) 3212 { 3213 /* Compile the HID value as an integer */ 3214 3215 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); 3216 3217 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger, 3218 &Subtable); 3219 if (ACPI_FAILURE (Status)) 3220 { 3221 return (Status); 3222 } 3223 } 3224 else 3225 { 3226 /* Compile the HID value as a string */ 3227 3228 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString, 3229 &Subtable); 3230 if (ACPI_FAILURE (Status)) 3231 { 3232 return (Status); 3233 } 3234 } 3235 3236 DtInsertSubtable (ParentTable, Subtable); 3237 3238 /* 3239 * Process the CID value. First, get the CID value as a string. 3240 */ 3241 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); 3242 3243 if (UtIsIdInteger ((UINT8 *) &Temp64)) 3244 { 3245 /* Compile the CID value as an integer */ 3246 3247 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); 3248 3249 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger, 3250 &Subtable); 3251 if (ACPI_FAILURE (Status)) 3252 { 3253 return (Status); 3254 } 3255 } 3256 else 3257 { 3258 /* Compile the CID value as a string */ 3259 3260 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString, 3261 &Subtable); 3262 if (ACPI_FAILURE (Status)) 3263 { 3264 return (Status); 3265 } 3266 } 3267 3268 DtInsertSubtable (ParentTable, Subtable); 3269 3270 /* 3271 * Process the UID value. First, get and decode the "UID Format" field (Integer). 3272 */ 3273 if (!*PFieldList) 3274 { 3275 return (AE_OK); 3276 } 3277 3278 DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0); 3279 3280 switch (Temp8) 3281 { 3282 case ACPI_IVRS_UID_NOT_PRESENT: 3283 break; 3284 3285 case ACPI_IVRS_UID_IS_INTEGER: 3286 3287 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger, 3288 &Subtable); 3289 if (ACPI_FAILURE (Status)) 3290 { 3291 return (Status); 3292 } 3293 DtInsertSubtable (ParentTable, Subtable); 3294 break; 3295 3296 case ACPI_IVRS_UID_IS_STRING: 3297 3298 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString, 3299 &Subtable); 3300 if (ACPI_FAILURE (Status)) 3301 { 3302 return (Status); 3303 } 3304 DtInsertSubtable (ParentTable, Subtable); 3305 break; 3306 3307 default: 3308 3309 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart, 3310 "IVRS Device Entry"); 3311 return (AE_ERROR); 3312 } 3313 3314 default: 3315 3316 /* All other subtable types come through here */ 3317 break; 3318 } 3319 } 3320 3321 return (AE_OK); 3322 } 3323 3324 3325 /****************************************************************************** 3326 * 3327 * FUNCTION: DtCompileRimt 3328 * 3329 * PARAMETERS: List - Current field list pointer 3330 * 3331 * RETURN: Status 3332 * 3333 * DESCRIPTION: Compile RIMT. 3334 * 3335 *****************************************************************************/ 3336 3337 ACPI_STATUS 3338 DtCompileRimt ( 3339 void **List) 3340 { 3341 ACPI_RIMT_PLATFORM_DEVICE *PlatDevNode; 3342 ACPI_RIMT_PCIE_RC *PcieRcNode; 3343 ACPI_TABLE_RIMT *Rimt; 3344 ACPI_RIMT_IOMMU *IommuNode; 3345 ACPI_RIMT_NODE *RimtNode; 3346 ACPI_STATUS Status; 3347 DT_SUBTABLE *Subtable; 3348 DT_SUBTABLE *ParentTable; 3349 DT_FIELD **PFieldList = (DT_FIELD **) List; 3350 DT_FIELD *SubtableStart; 3351 UINT32 NodeNumber; 3352 UINT32 NodeLength; 3353 UINT16 IdMappingNumber; 3354 UINT32 i; 3355 3356 3357 ParentTable = DtPeekSubtable (); 3358 3359 Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimt, &Subtable); 3360 if (ACPI_FAILURE (Status)) 3361 { 3362 return (Status); 3363 } 3364 3365 DtInsertSubtable (ParentTable, Subtable); 3366 3367 /* 3368 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 3369 * should be taken to avoid accessing ACPI_TABLE_HEADER fields. 3370 */ 3371 Rimt = ACPI_SUB_PTR (ACPI_TABLE_RIMT, Subtable->Buffer, 3372 sizeof (ACPI_TABLE_HEADER)); 3373 3374 NodeNumber = 0; 3375 while (*PFieldList) 3376 { 3377 SubtableStart = *PFieldList; 3378 Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtNodeHdr, &Subtable); 3379 3380 if (ACPI_FAILURE (Status)) 3381 { 3382 return (Status); 3383 } 3384 3385 DtInsertSubtable (ParentTable, Subtable); 3386 RimtNode = ACPI_CAST_PTR (ACPI_RIMT_NODE, Subtable->Buffer); 3387 NodeLength = ACPI_OFFSET (ACPI_RIMT_NODE, NodeData); 3388 3389 DtPushSubtable (Subtable); 3390 ParentTable = DtPeekSubtable (); 3391 3392 switch (RimtNode->Type) 3393 { 3394 case ACPI_RIMT_NODE_TYPE_IOMMU: 3395 3396 Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtIommu, 3397 &Subtable); 3398 if (ACPI_FAILURE (Status)) 3399 { 3400 return (Status); 3401 } 3402 3403 IommuNode = ACPI_CAST_PTR (ACPI_RIMT_IOMMU, Subtable->Buffer); 3404 DtInsertSubtable (ParentTable, Subtable); 3405 NodeLength += Subtable->Length; 3406 3407 for (i = 0; i < IommuNode->NumInterruptWires; i++) 3408 { 3409 while (*PFieldList) 3410 { 3411 Status = DtCompileTable (PFieldList, 3412 AcpiDmTableInfoRimtIommuWire, 3413 &Subtable); 3414 if (ACPI_FAILURE (Status)) 3415 { 3416 return (Status); 3417 } 3418 if (!Subtable) 3419 { 3420 break; 3421 } 3422 3423 DtInsertSubtable (ParentTable, Subtable); 3424 NodeLength += Subtable->Length; 3425 } 3426 } 3427 3428 break; 3429 3430 case ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX: 3431 3432 Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPcieRc, 3433 &Subtable); 3434 if (ACPI_FAILURE (Status)) 3435 { 3436 return (Status); 3437 } 3438 3439 DtInsertSubtable (ParentTable, Subtable); 3440 PcieRcNode = ACPI_CAST_PTR (ACPI_RIMT_PCIE_RC, Subtable->Buffer); 3441 NodeLength += Subtable->Length; 3442 3443 /* Compile Array of ID mappings */ 3444 3445 PcieRcNode->IdMappingOffset = (UINT16) NodeLength; 3446 IdMappingNumber = 0; 3447 while (*PFieldList) 3448 { 3449 Status = DtCompileTable (PFieldList, 3450 AcpiDmTableInfoRimtIdMapping, 3451 &Subtable); 3452 if (ACPI_FAILURE (Status)) 3453 { 3454 return (Status); 3455 } 3456 3457 if (!Subtable) 3458 { 3459 break; 3460 } 3461 3462 DtInsertSubtable (ParentTable, Subtable); 3463 NodeLength += sizeof (ACPI_RIMT_ID_MAPPING); 3464 IdMappingNumber++; 3465 } 3466 3467 PcieRcNode->NumIdMappings = IdMappingNumber; 3468 if (!IdMappingNumber) 3469 { 3470 PcieRcNode->IdMappingOffset = 0; 3471 } 3472 3473 break; 3474 3475 case ACPI_RIMT_NODE_TYPE_PLAT_DEVICE: 3476 3477 Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPlatDev, 3478 &Subtable); 3479 if (ACPI_FAILURE (Status)) 3480 { 3481 return (Status); 3482 } 3483 3484 DtInsertSubtable (ParentTable, Subtable); 3485 PlatDevNode = ACPI_CAST_PTR (ACPI_RIMT_PLATFORM_DEVICE, Subtable->Buffer); 3486 NodeLength += Subtable->Length; 3487 3488 /* 3489 * Padding - Variable-length data 3490 * Optionally allows the offset of the ID mappings to be used 3491 * for filling this field. 3492 */ 3493 Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPlatDevPad, 3494 &Subtable); 3495 if (ACPI_FAILURE (Status)) 3496 { 3497 return (Status); 3498 } 3499 3500 if (Subtable) 3501 { 3502 DtInsertSubtable (ParentTable, Subtable); 3503 NodeLength += Subtable->Length; 3504 } 3505 else 3506 { 3507 if (NodeLength > PlatDevNode->IdMappingOffset) 3508 { 3509 return (AE_BAD_DATA); 3510 } 3511 3512 if (NodeLength < PlatDevNode->IdMappingOffset) 3513 { 3514 Status = DtCompilePadding ( 3515 PlatDevNode->IdMappingOffset - (UINT16) NodeLength, 3516 &Subtable); 3517 if (ACPI_FAILURE (Status)) 3518 { 3519 return (Status); 3520 } 3521 3522 DtInsertSubtable (ParentTable, Subtable); 3523 NodeLength = PlatDevNode->IdMappingOffset; 3524 } 3525 } 3526 3527 /* Compile Array of ID mappings */ 3528 3529 PlatDevNode->IdMappingOffset = (UINT16) NodeLength; 3530 IdMappingNumber = 0; 3531 while (*PFieldList) 3532 { 3533 Status = DtCompileTable (PFieldList, 3534 AcpiDmTableInfoRimtIdMapping, 3535 &Subtable); 3536 if (ACPI_FAILURE (Status)) 3537 { 3538 return (Status); 3539 } 3540 3541 if (!Subtable) 3542 { 3543 break; 3544 } 3545 3546 DtInsertSubtable (ParentTable, Subtable); 3547 NodeLength += sizeof (ACPI_RIMT_ID_MAPPING); 3548 IdMappingNumber++; 3549 } 3550 3551 PlatDevNode->NumIdMappings = IdMappingNumber; 3552 if (!IdMappingNumber) 3553 { 3554 PlatDevNode->IdMappingOffset = 0; 3555 } 3556 3557 break; 3558 3559 3560 default: 3561 3562 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "RIMT"); 3563 return (AE_ERROR); 3564 } 3565 3566 DtPopSubtable (); 3567 ParentTable = DtPeekSubtable (); 3568 NodeNumber++; 3569 } 3570 3571 Rimt->NumNodes = NodeNumber; 3572 return (AE_OK); 3573 } 3574