1 /****************************************************************************** 2 * 3 * Module Name: dttable1.c - handling for specific ACPI tables 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2023, 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 102 103 while (*PFieldList) 104 { 105 /* Compile the common error node header */ 106 107 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestHdr, 108 &Subtable); 109 if (ACPI_FAILURE (Status)) 110 { 111 return (Status); 112 } 113 114 ParentTable = DtPeekSubtable (); 115 DtInsertSubtable (ParentTable, Subtable); 116 117 /* Everything past the error node header will be a subtable */ 118 119 DtPushSubtable (Subtable); 120 121 /* 122 * Compile the node-specific structure (Based on the error 123 * node header Type field) 124 */ 125 ErrorNodeHeader = ACPI_CAST_PTR (ACPI_AEST_HEADER, Subtable->Buffer); 126 127 /* Point past the common error node header */ 128 129 Offset = sizeof (ACPI_AEST_HEADER); 130 ErrorNodeHeader->NodeSpecificOffset = Offset; 131 132 /* Decode the error node type */ 133 134 switch (ErrorNodeHeader->Type) 135 { 136 case ACPI_AEST_PROCESSOR_ERROR_NODE: 137 138 InfoTable = AcpiDmTableInfoAestProcError; 139 break; 140 141 case ACPI_AEST_MEMORY_ERROR_NODE: 142 143 InfoTable = AcpiDmTableInfoAestMemError; 144 break; 145 146 case ACPI_AEST_SMMU_ERROR_NODE: 147 148 InfoTable = AcpiDmTableInfoAestSmmuError; 149 break; 150 151 case ACPI_AEST_VENDOR_ERROR_NODE: 152 153 InfoTable = AcpiDmTableInfoAestVendorError; 154 break; 155 156 case ACPI_AEST_GIC_ERROR_NODE: 157 158 InfoTable = AcpiDmTableInfoAestGicError; 159 break; 160 161 /* Error case below */ 162 default: 163 AcpiOsPrintf ("Unknown AEST Subtable Type: %X\n", 164 ErrorNodeHeader->Type); 165 return (AE_ERROR); 166 } 167 168 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 169 if (ACPI_FAILURE (Status)) 170 { 171 return (Status); 172 } 173 174 /* Point past the node-specific structure */ 175 176 Offset += Subtable->Length; 177 ErrorNodeHeader->NodeInterfaceOffset = Offset; 178 179 ParentTable = DtPeekSubtable (); 180 DtInsertSubtable (ParentTable, Subtable); 181 182 /* Compile any additional node-specific substructures */ 183 184 if (ErrorNodeHeader->Type == ACPI_AEST_PROCESSOR_ERROR_NODE) 185 { 186 /* 187 * Special handling for PROCESSOR_ERROR_NODE subtables 188 * (to handle the Resource Substructure via the ResourceType 189 * field). 190 */ 191 AestProcessor = ACPI_CAST_PTR (ACPI_AEST_PROCESSOR, 192 Subtable->Buffer); 193 194 switch (AestProcessor->ResourceType) 195 { 196 case ACPI_AEST_CACHE_RESOURCE: 197 198 InfoTable = AcpiDmTableInfoAestCacheRsrc; 199 break; 200 201 case ACPI_AEST_TLB_RESOURCE: 202 203 InfoTable = AcpiDmTableInfoAestTlbRsrc; 204 break; 205 206 case ACPI_AEST_GENERIC_RESOURCE: 207 208 InfoTable = AcpiDmTableInfoAestGenRsrc; 209 AcpiOsPrintf ("Generic Resource Type (%X) is not supported at this time\n", 210 AestProcessor->ResourceType); 211 return (AE_ERROR); 212 213 /* Error case below */ 214 default: 215 AcpiOsPrintf ("Unknown AEST Processor Resource Type: %X\n", 216 AestProcessor->ResourceType); 217 return (AE_ERROR); 218 } 219 220 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 221 if (ACPI_FAILURE (Status)) 222 { 223 return (Status); 224 } 225 226 /* Point past the resource substructure subtable */ 227 228 Offset += Subtable->Length; 229 ErrorNodeHeader->NodeInterfaceOffset = Offset; 230 231 ParentTable = DtPeekSubtable (); 232 DtInsertSubtable (ParentTable, Subtable); 233 } 234 235 /* Compile the (required) node interface structure */ 236 237 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXface, 238 &Subtable); 239 if (ACPI_FAILURE (Status)) 240 { 241 return (Status); 242 } 243 244 ErrorNodeHeader->NodeInterruptOffset = 0; 245 ParentTable = DtPeekSubtable (); 246 DtInsertSubtable (ParentTable, Subtable); 247 248 /* Compile each of the node interrupt structures */ 249 250 if (ErrorNodeHeader->NodeInterruptCount) 251 { 252 /* Point to the first interrupt structure */ 253 254 Offset += Subtable->Length; 255 ErrorNodeHeader->NodeInterruptOffset = Offset; 256 } 257 258 /* Compile each of the interrupt structures */ 259 260 for (i = 0; i < ErrorNodeHeader->NodeInterruptCount; i++) 261 { 262 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXrupt, 263 &Subtable); 264 if (ACPI_FAILURE (Status)) 265 { 266 return (Status); 267 } 268 269 ParentTable = DtPeekSubtable (); 270 DtInsertSubtable (ParentTable, Subtable); 271 } 272 273 /* Prepare for the next AEST Error node */ 274 275 DtPopSubtable (); 276 } 277 278 return (AE_OK); 279 } 280 281 282 /****************************************************************************** 283 * 284 * FUNCTION: DtCompileApmt 285 * 286 * PARAMETERS: List - Current field list pointer 287 * 288 * RETURN: Status 289 * 290 * DESCRIPTION: Compile APMT. 291 * 292 *****************************************************************************/ 293 294 ACPI_STATUS 295 DtCompileApmt ( 296 void **List) 297 { 298 ACPI_STATUS Status; 299 ACPI_TABLE_HEADER *Header; 300 ACPI_APMT_NODE *ApmtNode; 301 ACPI_APMT_NODE *PeerApmtNode; 302 DT_SUBTABLE *Subtable; 303 DT_SUBTABLE *PeerSubtable; 304 DT_SUBTABLE *ParentTable; 305 DT_FIELD **PFieldList = (DT_FIELD**)List; 306 DT_FIELD *SubtableStart; 307 UINT32 CurLength; 308 char MsgBuffer[64] = ""; 309 310 ParentTable = DtPeekSubtable(); 311 312 Header = ACPI_CAST_PTR(ACPI_TABLE_HEADER, ParentTable->Buffer); 313 314 CurLength = sizeof(ACPI_TABLE_HEADER); 315 316 /* Walk the parse tree */ 317 318 while (*PFieldList) 319 { 320 /* APMT Node Subtable */ 321 322 SubtableStart = *PFieldList; 323 324 Status = DtCompileTable(PFieldList, AcpiDmTableInfoApmtNode, &Subtable); 325 326 if (ACPI_FAILURE(Status)) 327 { 328 return (Status); 329 } 330 331 ApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, Subtable->Buffer); 332 333 if (ApmtNode->Length != sizeof(ACPI_APMT_NODE)) 334 { 335 DtFatal(ASL_MSG_INVALID_LENGTH, SubtableStart, "APMT"); 336 return (AE_ERROR); 337 } 338 339 if (ApmtNode->Type >= ACPI_APMT_NODE_TYPE_COUNT) 340 { 341 snprintf(MsgBuffer, 64, "Node Type : 0x%X", ApmtNode->Type); 342 DtFatal(ASL_MSG_INVALID_TYPE, SubtableStart, MsgBuffer); 343 return (AE_ERROR); 344 } 345 346 PeerSubtable = DtGetNextSubtable(ParentTable, NULL); 347 348 /* Validate the node id needs to be unique. */ 349 while(PeerSubtable) 350 { 351 PeerApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, PeerSubtable->Buffer); 352 if (PeerApmtNode->Id == ApmtNode->Id) 353 { 354 snprintf(MsgBuffer, 64, "Node Id : 0x%X existed", ApmtNode->Id); 355 DtFatal(ASL_MSG_DUPLICATE_ITEM, SubtableStart, MsgBuffer); 356 return (AE_ERROR); 357 } 358 359 PeerSubtable = DtGetNextSubtable(ParentTable, PeerSubtable); 360 } 361 362 CurLength += ApmtNode->Length; 363 364 DtInsertSubtable(ParentTable, Subtable); 365 } 366 367 if (Header->Length != CurLength) 368 { 369 snprintf(MsgBuffer, 64, " - APMT Length : %u (expected: %u)", 370 Header->Length, CurLength); 371 DtFatal(ASL_MSG_INVALID_LENGTH, NULL, MsgBuffer); 372 return (AE_ERROR); 373 } 374 375 return (AE_OK); 376 } 377 378 /****************************************************************************** 379 * 380 * FUNCTION: DtCompileAsf 381 * 382 * PARAMETERS: List - Current field list pointer 383 * 384 * RETURN: Status 385 * 386 * DESCRIPTION: Compile ASF!. 387 * 388 *****************************************************************************/ 389 390 ACPI_STATUS 391 DtCompileAsf ( 392 void **List) 393 { 394 ACPI_ASF_INFO *AsfTable; 395 DT_SUBTABLE *Subtable; 396 DT_SUBTABLE *ParentTable; 397 ACPI_DMTABLE_INFO *InfoTable; 398 ACPI_DMTABLE_INFO *DataInfoTable = NULL; 399 UINT32 DataCount = 0; 400 ACPI_STATUS Status; 401 UINT32 i; 402 DT_FIELD **PFieldList = (DT_FIELD **) List; 403 DT_FIELD *SubtableStart; 404 405 406 while (*PFieldList) 407 { 408 SubtableStart = *PFieldList; 409 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr, 410 &Subtable); 411 if (ACPI_FAILURE (Status)) 412 { 413 return (Status); 414 } 415 416 ParentTable = DtPeekSubtable (); 417 DtInsertSubtable (ParentTable, Subtable); 418 DtPushSubtable (Subtable); 419 420 AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer); 421 422 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ 423 { 424 case ACPI_ASF_TYPE_INFO: 425 426 InfoTable = AcpiDmTableInfoAsf0; 427 break; 428 429 case ACPI_ASF_TYPE_ALERT: 430 431 InfoTable = AcpiDmTableInfoAsf1; 432 break; 433 434 case ACPI_ASF_TYPE_CONTROL: 435 436 InfoTable = AcpiDmTableInfoAsf2; 437 break; 438 439 case ACPI_ASF_TYPE_BOOT: 440 441 InfoTable = AcpiDmTableInfoAsf3; 442 break; 443 444 case ACPI_ASF_TYPE_ADDRESS: 445 446 InfoTable = AcpiDmTableInfoAsf4; 447 break; 448 449 default: 450 451 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); 452 return (AE_ERROR); 453 } 454 455 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 456 if (ACPI_FAILURE (Status)) 457 { 458 return (Status); 459 } 460 461 ParentTable = DtPeekSubtable (); 462 DtInsertSubtable (ParentTable, Subtable); 463 464 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ 465 { 466 case ACPI_ASF_TYPE_INFO: 467 468 DataInfoTable = NULL; 469 break; 470 471 case ACPI_ASF_TYPE_ALERT: 472 473 DataInfoTable = AcpiDmTableInfoAsf1a; 474 DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT, 475 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 476 sizeof (ACPI_ASF_HEADER)))->Alerts; 477 break; 478 479 case ACPI_ASF_TYPE_CONTROL: 480 481 DataInfoTable = AcpiDmTableInfoAsf2a; 482 DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE, 483 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 484 sizeof (ACPI_ASF_HEADER)))->Controls; 485 break; 486 487 case ACPI_ASF_TYPE_BOOT: 488 489 DataInfoTable = NULL; 490 break; 491 492 case ACPI_ASF_TYPE_ADDRESS: 493 494 DataInfoTable = TableInfoAsfAddress; 495 DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS, 496 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 497 sizeof (ACPI_ASF_HEADER)))->Devices; 498 break; 499 500 default: 501 502 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); 503 return (AE_ERROR); 504 } 505 506 if (DataInfoTable) 507 { 508 switch (AsfTable->Header.Type & 0x7F) 509 { 510 case ACPI_ASF_TYPE_ADDRESS: 511 512 while (DataCount > 0) 513 { 514 Status = DtCompileTable (PFieldList, DataInfoTable, 515 &Subtable); 516 if (ACPI_FAILURE (Status)) 517 { 518 return (Status); 519 } 520 521 DtInsertSubtable (ParentTable, Subtable); 522 DataCount = DataCount - Subtable->Length; 523 } 524 break; 525 526 default: 527 528 for (i = 0; i < DataCount; i++) 529 { 530 Status = DtCompileTable (PFieldList, DataInfoTable, 531 &Subtable); 532 if (ACPI_FAILURE (Status)) 533 { 534 return (Status); 535 } 536 537 DtInsertSubtable (ParentTable, Subtable); 538 } 539 break; 540 } 541 } 542 543 DtPopSubtable (); 544 } 545 546 return (AE_OK); 547 } 548 549 /****************************************************************************** 550 * 551 * FUNCTION: DtCompileAspt 552 * 553 * PARAMETERS: List - Current field list pointer 554 * 555 * RETURN: Status 556 * 557 * DESCRIPTION: Compile ASPT. 558 * 559 *****************************************************************************/ 560 561 ACPI_STATUS 562 DtCompileAspt ( 563 void **List) 564 { 565 ACPI_ASPT_HEADER *AsptTable; 566 DT_SUBTABLE *Subtable; 567 DT_SUBTABLE *ParentTable; 568 ACPI_DMTABLE_INFO *InfoTable; 569 ACPI_STATUS Status; 570 DT_FIELD **PFieldList = (DT_FIELD **) List; 571 DT_FIELD *SubtableStart; 572 573 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAspt, &Subtable); 574 if (ACPI_FAILURE (Status)) 575 { 576 return (Status); 577 } 578 579 ParentTable = DtPeekSubtable (); 580 DtInsertSubtable (ParentTable, Subtable); 581 582 while (*PFieldList) 583 { 584 SubtableStart = *PFieldList; 585 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsptHdr, 586 &Subtable); 587 if (ACPI_FAILURE (Status)) 588 { 589 return (Status); 590 } 591 592 ParentTable = DtPeekSubtable (); 593 DtInsertSubtable (ParentTable, Subtable); 594 DtPushSubtable (Subtable); 595 596 AsptTable = ACPI_CAST_PTR (ACPI_ASPT_HEADER, Subtable->Buffer); 597 598 switch (AsptTable->Type) /* Mask off top bit */ 599 { 600 case ACPI_ASPT_TYPE_GLOBAL_REGS: 601 602 InfoTable = AcpiDmTableInfoAspt0; 603 break; 604 605 case ACPI_ASPT_TYPE_SEV_MBOX_REGS: 606 607 InfoTable = AcpiDmTableInfoAspt1; 608 break; 609 610 case ACPI_ASPT_TYPE_ACPI_MBOX_REGS: 611 612 InfoTable = AcpiDmTableInfoAspt2; 613 break; 614 615 default: 616 617 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASPT"); 618 return (AE_ERROR); 619 } 620 621 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 622 if (ACPI_FAILURE (Status)) 623 { 624 return (Status); 625 } 626 ParentTable = DtPeekSubtable (); 627 DtInsertSubtable (ParentTable, Subtable); 628 DtPopSubtable (); 629 } 630 631 return (AE_OK); 632 } 633 634 635 /****************************************************************************** 636 * 637 * FUNCTION: DtCompileCdat 638 * 639 * PARAMETERS: List - Current field list pointer 640 * 641 * RETURN: Status 642 * 643 * DESCRIPTION: Compile CDAT. 644 * 645 *****************************************************************************/ 646 647 ACPI_STATUS 648 DtCompileCdat ( 649 void **List) 650 { 651 ACPI_STATUS Status = AE_OK; 652 DT_SUBTABLE *Subtable; 653 DT_SUBTABLE *ParentTable; 654 DT_FIELD **PFieldList = (DT_FIELD **) List; 655 ACPI_CDAT_HEADER *CdatHeader; 656 ACPI_DMTABLE_INFO *InfoTable = NULL; 657 DT_FIELD *SubtableStart; 658 659 660 /* Walk the parse tree. 661 * 662 * Note: Main table consists of only the CDAT table header 663 * (This is not the standard ACPI table header, however)-- 664 * Followed by some number of subtables. 665 */ 666 while (*PFieldList) 667 { 668 SubtableStart = *PFieldList; 669 670 /* Compile the expected CDAT Subtable header */ 671 672 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatHeader, 673 &Subtable); 674 if (ACPI_FAILURE (Status)) 675 { 676 return (Status); 677 } 678 679 ParentTable = DtPeekSubtable (); 680 DtInsertSubtable (ParentTable, Subtable); 681 DtPushSubtable (Subtable); 682 683 CdatHeader = ACPI_CAST_PTR (ACPI_CDAT_HEADER, Subtable->Buffer); 684 685 /* Decode the subtable by type */ 686 687 switch (CdatHeader->Type) 688 { 689 case ACPI_CDAT_TYPE_DSMAS: 690 InfoTable = AcpiDmTableInfoCdat0; 691 break; 692 693 case ACPI_CDAT_TYPE_DSLBIS: 694 InfoTable = AcpiDmTableInfoCdat1; 695 break; 696 697 case ACPI_CDAT_TYPE_DSMSCIS: 698 InfoTable = AcpiDmTableInfoCdat2; 699 break; 700 701 case ACPI_CDAT_TYPE_DSIS: 702 InfoTable = AcpiDmTableInfoCdat3; 703 break; 704 705 case ACPI_CDAT_TYPE_DSEMTS: 706 InfoTable = AcpiDmTableInfoCdat4; 707 break; 708 709 case ACPI_CDAT_TYPE_SSLBIS: 710 InfoTable = AcpiDmTableInfoCdat5; 711 break; 712 713 default: 714 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CDAT"); 715 } 716 717 /* Compile the CDAT subtable */ 718 719 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 720 if (ACPI_FAILURE (Status)) 721 { 722 return (Status); 723 } 724 725 ParentTable = DtPeekSubtable (); 726 DtInsertSubtable (ParentTable, Subtable); 727 728 switch (CdatHeader->Type) 729 { 730 /* Multiple entries supported for this type */ 731 732 case ACPI_CDAT_TYPE_SSLBIS: 733 734 /* 735 * Check for multiple SSLBEs 736 */ 737 while (*PFieldList && !AcpiUtStricmp ((*PFieldList)->Name, "Port X ID")) 738 { 739 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatEntries, &Subtable); 740 if (ACPI_FAILURE (Status)) 741 { 742 return (Status); 743 } 744 ParentTable = DtPeekSubtable (); 745 DtInsertSubtable (ParentTable, Subtable); 746 } 747 break; 748 749 default: 750 break; 751 } 752 753 /* Pop off the CDAT Subtable header subtree */ 754 755 DtPopSubtable (); 756 } 757 758 return (AE_OK); 759 } 760 761 762 /****************************************************************************** 763 * 764 * FUNCTION: DtCompileCedt 765 * 766 * PARAMETERS: List - Current field list pointer 767 * 768 * RETURN: Status 769 * 770 * DESCRIPTION: Compile CEDT. 771 * 772 *****************************************************************************/ 773 774 ACPI_STATUS 775 DtCompileCedt ( 776 void **List) 777 { 778 ACPI_STATUS Status; 779 DT_SUBTABLE *Subtable; 780 DT_SUBTABLE *ParentTable; 781 DT_FIELD **PFieldList = (DT_FIELD **) List; 782 ACPI_CEDT_HEADER *CedtHeader; 783 DT_FIELD *SubtableStart; 784 785 786 /* Walk the parse tree */ 787 788 while (*PFieldList) 789 { 790 /* if CFMWS and has more than one target, then set to zero later */ 791 792 int InsertFlag = 1; 793 SubtableStart = *PFieldList; 794 795 /* CEDT Header */ 796 797 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr, 798 &Subtable); 799 if (ACPI_FAILURE (Status)) 800 { 801 return (Status); 802 } 803 804 ParentTable = DtPeekSubtable (); 805 DtInsertSubtable (ParentTable, Subtable); 806 DtPushSubtable (Subtable); 807 808 CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer); 809 810 switch (CedtHeader->Type) 811 { 812 case ACPI_CEDT_TYPE_CHBS: 813 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable); 814 if (ACPI_FAILURE (Status)) 815 { 816 return (Status); 817 } 818 break; 819 case ACPI_CEDT_TYPE_CFMWS: { 820 unsigned char *dump; 821 unsigned int idx, offset, max = 0; 822 823 /* Compile table with first "Interleave target" */ 824 825 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1, &Subtable); 826 if (ACPI_FAILURE (Status)) 827 { 828 return (Status); 829 } 830 831 /* Look in buffer for the number of targets */ 832 offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CFMWS, InterleaveWays); 833 dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt1 */ 834 max = 0x01 << dump[offset]; /* 2^max, so 0=1, 1=2, 2=4, 3=8. 8 is MAX */ 835 if (max > 8) max=1; /* Error in encoding Interleaving Ways. */ 836 if (max == 1) /* if only one target, then break here. */ 837 break; /* break if only one target. */ 838 839 /* We need to add more interleave targets, so write the current Subtable. */ 840 841 ParentTable = DtPeekSubtable (); 842 DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt1 table so we can put in */ 843 DtPushSubtable (Subtable); /* the targets > the first. */ 844 845 /* Now, find out all interleave targets beyond the first. */ 846 847 for (idx = 1; idx < max; idx++) { 848 ParentTable = DtPeekSubtable (); 849 850 if (*PFieldList) 851 { 852 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1_te, &Subtable); 853 if (ACPI_FAILURE (Status)) 854 { 855 return (Status); 856 } 857 if (Subtable) 858 { 859 DtInsertSubtable (ParentTable, Subtable); /* got a target, so insert table. */ 860 InsertFlag = 0; 861 } 862 } 863 } 864 865 DtPopSubtable (); 866 ParentTable = DtPeekSubtable (); 867 break; 868 } 869 870 default: 871 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT"); 872 return (AE_ERROR); 873 } 874 875 ParentTable = DtPeekSubtable (); 876 if (InsertFlag == 1) { 877 DtInsertSubtable (ParentTable, Subtable); 878 } 879 DtPopSubtable (); 880 } 881 882 return (AE_OK); 883 } 884 885 886 /****************************************************************************** 887 * 888 * FUNCTION: DtCompileCpep 889 * 890 * PARAMETERS: List - Current field list pointer 891 * 892 * RETURN: Status 893 * 894 * DESCRIPTION: Compile CPEP. 895 * 896 *****************************************************************************/ 897 898 ACPI_STATUS 899 DtCompileCpep ( 900 void **List) 901 { 902 ACPI_STATUS Status; 903 904 905 Status = DtCompileTwoSubtables (List, 906 AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0); 907 return (Status); 908 } 909 910 911 /****************************************************************************** 912 * 913 * FUNCTION: DtCompileCsrt 914 * 915 * PARAMETERS: List - Current field list pointer 916 * 917 * RETURN: Status 918 * 919 * DESCRIPTION: Compile CSRT. 920 * 921 *****************************************************************************/ 922 923 ACPI_STATUS 924 DtCompileCsrt ( 925 void **List) 926 { 927 ACPI_STATUS Status = AE_OK; 928 DT_SUBTABLE *Subtable; 929 DT_SUBTABLE *ParentTable; 930 DT_FIELD **PFieldList = (DT_FIELD **) List; 931 UINT32 DescriptorCount; 932 UINT32 GroupLength; 933 934 935 /* Subtables (Resource Groups) */ 936 937 ParentTable = DtPeekSubtable (); 938 while (*PFieldList) 939 { 940 /* Resource group subtable */ 941 942 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0, 943 &Subtable); 944 if (ACPI_FAILURE (Status)) 945 { 946 return (Status); 947 } 948 949 /* Compute the number of resource descriptors */ 950 951 GroupLength = 952 (ACPI_CAST_PTR (ACPI_CSRT_GROUP, 953 Subtable->Buffer))->Length - 954 (ACPI_CAST_PTR (ACPI_CSRT_GROUP, 955 Subtable->Buffer))->SharedInfoLength - 956 sizeof (ACPI_CSRT_GROUP); 957 958 DescriptorCount = (GroupLength / 959 sizeof (ACPI_CSRT_DESCRIPTOR)); 960 961 DtInsertSubtable (ParentTable, Subtable); 962 DtPushSubtable (Subtable); 963 ParentTable = DtPeekSubtable (); 964 965 /* Shared info subtable (One per resource group) */ 966 967 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1, 968 &Subtable); 969 if (ACPI_FAILURE (Status)) 970 { 971 return (Status); 972 } 973 974 DtInsertSubtable (ParentTable, Subtable); 975 976 /* Sub-Subtables (Resource Descriptors) */ 977 978 while (*PFieldList && DescriptorCount) 979 { 980 981 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2, 982 &Subtable); 983 if (ACPI_FAILURE (Status)) 984 { 985 return (Status); 986 } 987 988 DtInsertSubtable (ParentTable, Subtable); 989 990 DtPushSubtable (Subtable); 991 ParentTable = DtPeekSubtable (); 992 if (*PFieldList) 993 { 994 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a, 995 &Subtable); 996 if (ACPI_FAILURE (Status)) 997 { 998 return (Status); 999 } 1000 if (Subtable) 1001 { 1002 DtInsertSubtable (ParentTable, Subtable); 1003 } 1004 } 1005 1006 DtPopSubtable (); 1007 ParentTable = DtPeekSubtable (); 1008 DescriptorCount--; 1009 } 1010 1011 DtPopSubtable (); 1012 ParentTable = DtPeekSubtable (); 1013 } 1014 1015 return (Status); 1016 } 1017 1018 1019 /****************************************************************************** 1020 * 1021 * FUNCTION: DtCompileDbg2 1022 * 1023 * PARAMETERS: List - Current field list pointer 1024 * 1025 * RETURN: Status 1026 * 1027 * DESCRIPTION: Compile DBG2. 1028 * 1029 *****************************************************************************/ 1030 1031 ACPI_STATUS 1032 DtCompileDbg2 ( 1033 void **List) 1034 { 1035 ACPI_STATUS Status; 1036 DT_SUBTABLE *Subtable; 1037 DT_SUBTABLE *ParentTable; 1038 DT_FIELD **PFieldList = (DT_FIELD **) List; 1039 UINT32 SubtableCount; 1040 ACPI_DBG2_HEADER *Dbg2Header; 1041 ACPI_DBG2_DEVICE *DeviceInfo; 1042 UINT16 CurrentOffset; 1043 UINT32 i; 1044 1045 1046 /* Main table */ 1047 1048 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable); 1049 if (ACPI_FAILURE (Status)) 1050 { 1051 return (Status); 1052 } 1053 1054 ParentTable = DtPeekSubtable (); 1055 DtInsertSubtable (ParentTable, Subtable); 1056 1057 /* Main table fields */ 1058 1059 Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer); 1060 Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF ( 1061 ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header); 1062 1063 SubtableCount = Dbg2Header->InfoCount; 1064 DtPushSubtable (Subtable); 1065 1066 /* Process all Device Information subtables (Count = InfoCount) */ 1067 1068 while (*PFieldList && SubtableCount) 1069 { 1070 /* Subtable: Debug Device Information */ 1071 1072 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device, 1073 &Subtable); 1074 if (ACPI_FAILURE (Status)) 1075 { 1076 return (Status); 1077 } 1078 1079 DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer); 1080 CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE); 1081 1082 ParentTable = DtPeekSubtable (); 1083 DtInsertSubtable (ParentTable, Subtable); 1084 DtPushSubtable (Subtable); 1085 1086 ParentTable = DtPeekSubtable (); 1087 1088 /* BaseAddressRegister GAS array (Required, size is RegisterCount) */ 1089 1090 DeviceInfo->BaseAddressOffset = CurrentOffset; 1091 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) 1092 { 1093 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr, 1094 &Subtable); 1095 if (ACPI_FAILURE (Status)) 1096 { 1097 return (Status); 1098 } 1099 1100 CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS); 1101 DtInsertSubtable (ParentTable, Subtable); 1102 } 1103 1104 /* AddressSize array (Required, size = RegisterCount) */ 1105 1106 DeviceInfo->AddressSizeOffset = CurrentOffset; 1107 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) 1108 { 1109 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size, 1110 &Subtable); 1111 if (ACPI_FAILURE (Status)) 1112 { 1113 return (Status); 1114 } 1115 1116 CurrentOffset += (UINT16) sizeof (UINT32); 1117 DtInsertSubtable (ParentTable, Subtable); 1118 } 1119 1120 /* NamespaceString device identifier (Required, size = NamePathLength) */ 1121 1122 DeviceInfo->NamepathOffset = CurrentOffset; 1123 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name, 1124 &Subtable); 1125 if (ACPI_FAILURE (Status)) 1126 { 1127 return (Status); 1128 } 1129 1130 /* Update the device info header */ 1131 1132 DeviceInfo->NamepathLength = (UINT16) Subtable->Length; 1133 CurrentOffset += (UINT16) DeviceInfo->NamepathLength; 1134 DtInsertSubtable (ParentTable, Subtable); 1135 1136 /* OemData - Variable-length data (Optional, size = OemDataLength) */ 1137 1138 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData, 1139 &Subtable); 1140 if (Status == AE_END_OF_TABLE) 1141 { 1142 /* optional field was not found and we're at the end of the file */ 1143 1144 goto subtableDone; 1145 } 1146 else if (ACPI_FAILURE (Status)) 1147 { 1148 return (Status); 1149 } 1150 1151 /* Update the device info header (zeros if no OEM data present) */ 1152 1153 DeviceInfo->OemDataOffset = 0; 1154 DeviceInfo->OemDataLength = 0; 1155 1156 /* Optional subtable (OemData) */ 1157 1158 if (Subtable && Subtable->Length) 1159 { 1160 DeviceInfo->OemDataOffset = CurrentOffset; 1161 DeviceInfo->OemDataLength = (UINT16) Subtable->Length; 1162 1163 DtInsertSubtable (ParentTable, Subtable); 1164 } 1165 subtableDone: 1166 SubtableCount--; 1167 DtPopSubtable (); /* Get next Device Information subtable */ 1168 } 1169 1170 DtPopSubtable (); 1171 return (AE_OK); 1172 } 1173 1174 1175 /****************************************************************************** 1176 * 1177 * FUNCTION: DtCompileDmar 1178 * 1179 * PARAMETERS: List - Current field list pointer 1180 * 1181 * RETURN: Status 1182 * 1183 * DESCRIPTION: Compile DMAR. 1184 * 1185 *****************************************************************************/ 1186 1187 ACPI_STATUS 1188 DtCompileDmar ( 1189 void **List) 1190 { 1191 ACPI_STATUS Status; 1192 DT_SUBTABLE *Subtable; 1193 DT_SUBTABLE *ParentTable; 1194 DT_FIELD **PFieldList = (DT_FIELD **) List; 1195 DT_FIELD *SubtableStart; 1196 ACPI_DMTABLE_INFO *InfoTable; 1197 ACPI_DMAR_HEADER *DmarHeader; 1198 ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope; 1199 UINT32 DeviceScopeLength; 1200 UINT32 PciPathLength; 1201 1202 1203 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable); 1204 if (ACPI_FAILURE (Status)) 1205 { 1206 return (Status); 1207 } 1208 1209 ParentTable = DtPeekSubtable (); 1210 DtInsertSubtable (ParentTable, Subtable); 1211 DtPushSubtable (Subtable); 1212 1213 while (*PFieldList) 1214 { 1215 /* DMAR Header */ 1216 1217 SubtableStart = *PFieldList; 1218 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr, 1219 &Subtable); 1220 if (ACPI_FAILURE (Status)) 1221 { 1222 return (Status); 1223 } 1224 1225 ParentTable = DtPeekSubtable (); 1226 DtInsertSubtable (ParentTable, Subtable); 1227 DtPushSubtable (Subtable); 1228 1229 DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer); 1230 1231 switch (DmarHeader->Type) 1232 { 1233 case ACPI_DMAR_TYPE_HARDWARE_UNIT: 1234 1235 InfoTable = AcpiDmTableInfoDmar0; 1236 break; 1237 1238 case ACPI_DMAR_TYPE_RESERVED_MEMORY: 1239 1240 InfoTable = AcpiDmTableInfoDmar1; 1241 break; 1242 1243 case ACPI_DMAR_TYPE_ROOT_ATS: 1244 1245 InfoTable = AcpiDmTableInfoDmar2; 1246 break; 1247 1248 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY: 1249 1250 InfoTable = AcpiDmTableInfoDmar3; 1251 break; 1252 1253 case ACPI_DMAR_TYPE_NAMESPACE: 1254 1255 InfoTable = AcpiDmTableInfoDmar4; 1256 break; 1257 1258 case ACPI_DMAR_TYPE_SATC: 1259 1260 InfoTable = AcpiDmTableInfoDmar5; 1261 break; 1262 1263 default: 1264 1265 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR"); 1266 return (AE_ERROR); 1267 } 1268 1269 /* DMAR Subtable */ 1270 1271 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1272 if (ACPI_FAILURE (Status)) 1273 { 1274 return (Status); 1275 } 1276 1277 ParentTable = DtPeekSubtable (); 1278 DtInsertSubtable (ParentTable, Subtable); 1279 1280 /* 1281 * Optional Device Scope subtables 1282 */ 1283 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) || 1284 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE)) 1285 { 1286 /* These types do not support device scopes */ 1287 1288 DtPopSubtable (); 1289 continue; 1290 } 1291 1292 DtPushSubtable (Subtable); 1293 DeviceScopeLength = DmarHeader->Length - Subtable->Length - 1294 ParentTable->Length; 1295 while (DeviceScopeLength) 1296 { 1297 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope, 1298 &Subtable); 1299 if (Status == AE_NOT_FOUND) 1300 { 1301 break; 1302 } 1303 1304 ParentTable = DtPeekSubtable (); 1305 DtInsertSubtable (ParentTable, Subtable); 1306 DtPushSubtable (Subtable); 1307 1308 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer); 1309 1310 /* Optional PCI Paths */ 1311 1312 PciPathLength = DmarDeviceScope->Length - Subtable->Length; 1313 while (PciPathLength) 1314 { 1315 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath, 1316 &Subtable); 1317 if (Status == AE_NOT_FOUND) 1318 { 1319 DtPopSubtable (); 1320 break; 1321 } 1322 1323 ParentTable = DtPeekSubtable (); 1324 DtInsertSubtable (ParentTable, Subtable); 1325 PciPathLength -= Subtable->Length; 1326 } 1327 1328 DtPopSubtable (); 1329 DeviceScopeLength -= DmarDeviceScope->Length; 1330 } 1331 1332 DtPopSubtable (); 1333 DtPopSubtable (); 1334 } 1335 1336 return (AE_OK); 1337 } 1338 1339 1340 /****************************************************************************** 1341 * 1342 * FUNCTION: DtCompileDrtm 1343 * 1344 * PARAMETERS: List - Current field list pointer 1345 * 1346 * RETURN: Status 1347 * 1348 * DESCRIPTION: Compile DRTM. 1349 * 1350 *****************************************************************************/ 1351 1352 ACPI_STATUS 1353 DtCompileDrtm ( 1354 void **List) 1355 { 1356 ACPI_STATUS Status; 1357 DT_SUBTABLE *Subtable; 1358 DT_SUBTABLE *ParentTable; 1359 DT_FIELD **PFieldList = (DT_FIELD **) List; 1360 UINT32 Count; 1361 /* ACPI_TABLE_DRTM *Drtm; */ 1362 ACPI_DRTM_VTABLE_LIST *DrtmVtl; 1363 ACPI_DRTM_RESOURCE_LIST *DrtmRl; 1364 /* ACPI_DRTM_DPS_ID *DrtmDps; */ 1365 1366 1367 ParentTable = DtPeekSubtable (); 1368 1369 /* Compile DRTM header */ 1370 1371 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm, 1372 &Subtable); 1373 if (ACPI_FAILURE (Status)) 1374 { 1375 return (Status); 1376 } 1377 DtInsertSubtable (ParentTable, Subtable); 1378 1379 /* 1380 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 1381 * should be taken to avoid accessing ACPI_TABLE_HADER fields. 1382 */ 1383 #if 0 1384 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM, 1385 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 1386 #endif 1387 /* Compile VTL */ 1388 1389 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0, 1390 &Subtable); 1391 if (ACPI_FAILURE (Status)) 1392 { 1393 return (Status); 1394 } 1395 1396 DtInsertSubtable (ParentTable, Subtable); 1397 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer); 1398 1399 DtPushSubtable (Subtable); 1400 ParentTable = DtPeekSubtable (); 1401 Count = 0; 1402 1403 while (*PFieldList) 1404 { 1405 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a, 1406 &Subtable); 1407 if (ACPI_FAILURE (Status)) 1408 { 1409 return (Status); 1410 } 1411 if (!Subtable) 1412 { 1413 break; 1414 } 1415 DtInsertSubtable (ParentTable, Subtable); 1416 Count++; 1417 } 1418 1419 DrtmVtl->ValidatedTableCount = Count; 1420 DtPopSubtable (); 1421 ParentTable = DtPeekSubtable (); 1422 1423 /* Compile RL */ 1424 1425 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1, 1426 &Subtable); 1427 if (ACPI_FAILURE (Status)) 1428 { 1429 return (Status); 1430 } 1431 1432 DtInsertSubtable (ParentTable, Subtable); 1433 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer); 1434 1435 DtPushSubtable (Subtable); 1436 ParentTable = DtPeekSubtable (); 1437 Count = 0; 1438 1439 while (*PFieldList) 1440 { 1441 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a, 1442 &Subtable); 1443 if (ACPI_FAILURE (Status)) 1444 { 1445 return (Status); 1446 } 1447 1448 if (!Subtable) 1449 { 1450 break; 1451 } 1452 1453 DtInsertSubtable (ParentTable, Subtable); 1454 Count++; 1455 } 1456 1457 DrtmRl->ResourceCount = Count; 1458 DtPopSubtable (); 1459 ParentTable = DtPeekSubtable (); 1460 1461 /* Compile DPS */ 1462 1463 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2, 1464 &Subtable); 1465 if (ACPI_FAILURE (Status)) 1466 { 1467 return (Status); 1468 } 1469 DtInsertSubtable (ParentTable, Subtable); 1470 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/ 1471 1472 1473 return (AE_OK); 1474 } 1475 1476 1477 /****************************************************************************** 1478 * 1479 * FUNCTION: DtCompileEinj 1480 * 1481 * PARAMETERS: List - Current field list pointer 1482 * 1483 * RETURN: Status 1484 * 1485 * DESCRIPTION: Compile EINJ. 1486 * 1487 *****************************************************************************/ 1488 1489 ACPI_STATUS 1490 DtCompileEinj ( 1491 void **List) 1492 { 1493 ACPI_STATUS Status; 1494 1495 1496 Status = DtCompileTwoSubtables (List, 1497 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0); 1498 return (Status); 1499 } 1500 1501 1502 /****************************************************************************** 1503 * 1504 * FUNCTION: DtCompileErst 1505 * 1506 * PARAMETERS: List - Current field list pointer 1507 * 1508 * RETURN: Status 1509 * 1510 * DESCRIPTION: Compile ERST. 1511 * 1512 *****************************************************************************/ 1513 1514 ACPI_STATUS 1515 DtCompileErst ( 1516 void **List) 1517 { 1518 ACPI_STATUS Status; 1519 1520 1521 Status = DtCompileTwoSubtables (List, 1522 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0); 1523 return (Status); 1524 } 1525 1526 1527 /****************************************************************************** 1528 * 1529 * FUNCTION: DtCompileGtdt 1530 * 1531 * PARAMETERS: List - Current field list pointer 1532 * 1533 * RETURN: Status 1534 * 1535 * DESCRIPTION: Compile GTDT. 1536 * 1537 *****************************************************************************/ 1538 1539 ACPI_STATUS 1540 DtCompileGtdt ( 1541 void **List) 1542 { 1543 ACPI_STATUS Status; 1544 DT_SUBTABLE *Subtable; 1545 DT_SUBTABLE *ParentTable; 1546 DT_FIELD **PFieldList = (DT_FIELD **) List; 1547 DT_FIELD *SubtableStart; 1548 ACPI_SUBTABLE_HEADER *GtdtHeader; 1549 ACPI_DMTABLE_INFO *InfoTable; 1550 UINT32 GtCount; 1551 ACPI_TABLE_HEADER *Header; 1552 1553 1554 ParentTable = DtPeekSubtable (); 1555 1556 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 1557 1558 /* Compile the main table */ 1559 1560 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt, 1561 &Subtable); 1562 if (ACPI_FAILURE (Status)) 1563 { 1564 return (Status); 1565 } 1566 1567 /* GTDT revision 3 later contains 2 extra fields before subtables */ 1568 1569 if (Header->Revision > 2) 1570 { 1571 ParentTable = DtPeekSubtable (); 1572 DtInsertSubtable (ParentTable, Subtable); 1573 1574 Status = DtCompileTable (PFieldList, 1575 AcpiDmTableInfoGtdtEl2, &Subtable); 1576 if (ACPI_FAILURE (Status)) 1577 { 1578 return (Status); 1579 } 1580 } 1581 1582 ParentTable = DtPeekSubtable (); 1583 DtInsertSubtable (ParentTable, Subtable); 1584 1585 while (*PFieldList) 1586 { 1587 SubtableStart = *PFieldList; 1588 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr, 1589 &Subtable); 1590 if (ACPI_FAILURE (Status)) 1591 { 1592 return (Status); 1593 } 1594 1595 ParentTable = DtPeekSubtable (); 1596 DtInsertSubtable (ParentTable, Subtable); 1597 DtPushSubtable (Subtable); 1598 1599 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer); 1600 1601 switch (GtdtHeader->Type) 1602 { 1603 case ACPI_GTDT_TYPE_TIMER_BLOCK: 1604 1605 InfoTable = AcpiDmTableInfoGtdt0; 1606 break; 1607 1608 case ACPI_GTDT_TYPE_WATCHDOG: 1609 1610 InfoTable = AcpiDmTableInfoGtdt1; 1611 break; 1612 1613 default: 1614 1615 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT"); 1616 return (AE_ERROR); 1617 } 1618 1619 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1620 if (ACPI_FAILURE (Status)) 1621 { 1622 return (Status); 1623 } 1624 1625 ParentTable = DtPeekSubtable (); 1626 DtInsertSubtable (ParentTable, Subtable); 1627 1628 /* 1629 * Additional GT block subtable data 1630 */ 1631 1632 switch (GtdtHeader->Type) 1633 { 1634 case ACPI_GTDT_TYPE_TIMER_BLOCK: 1635 1636 DtPushSubtable (Subtable); 1637 ParentTable = DtPeekSubtable (); 1638 1639 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK, 1640 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount; 1641 1642 while (GtCount) 1643 { 1644 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a, 1645 &Subtable); 1646 if (ACPI_FAILURE (Status)) 1647 { 1648 return (Status); 1649 } 1650 1651 DtInsertSubtable (ParentTable, Subtable); 1652 GtCount--; 1653 } 1654 1655 DtPopSubtable (); 1656 break; 1657 1658 default: 1659 1660 break; 1661 } 1662 1663 DtPopSubtable (); 1664 } 1665 1666 return (AE_OK); 1667 } 1668 1669 1670 /****************************************************************************** 1671 * 1672 * FUNCTION: DtCompileFpdt 1673 * 1674 * PARAMETERS: List - Current field list pointer 1675 * 1676 * RETURN: Status 1677 * 1678 * DESCRIPTION: Compile FPDT. 1679 * 1680 *****************************************************************************/ 1681 1682 ACPI_STATUS 1683 DtCompileFpdt ( 1684 void **List) 1685 { 1686 ACPI_STATUS Status; 1687 ACPI_FPDT_HEADER *FpdtHeader; 1688 DT_SUBTABLE *Subtable; 1689 DT_SUBTABLE *ParentTable; 1690 ACPI_DMTABLE_INFO *InfoTable; 1691 DT_FIELD **PFieldList = (DT_FIELD **) List; 1692 DT_FIELD *SubtableStart; 1693 1694 1695 while (*PFieldList) 1696 { 1697 SubtableStart = *PFieldList; 1698 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr, 1699 &Subtable); 1700 if (ACPI_FAILURE (Status)) 1701 { 1702 return (Status); 1703 } 1704 1705 ParentTable = DtPeekSubtable (); 1706 DtInsertSubtable (ParentTable, Subtable); 1707 DtPushSubtable (Subtable); 1708 1709 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer); 1710 1711 switch (FpdtHeader->Type) 1712 { 1713 case ACPI_FPDT_TYPE_BOOT: 1714 1715 InfoTable = AcpiDmTableInfoFpdt0; 1716 break; 1717 1718 case ACPI_FPDT_TYPE_S3PERF: 1719 1720 InfoTable = AcpiDmTableInfoFpdt1; 1721 break; 1722 1723 default: 1724 1725 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT"); 1726 return (AE_ERROR); 1727 break; 1728 } 1729 1730 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1731 if (ACPI_FAILURE (Status)) 1732 { 1733 return (Status); 1734 } 1735 1736 ParentTable = DtPeekSubtable (); 1737 DtInsertSubtable (ParentTable, Subtable); 1738 DtPopSubtable (); 1739 } 1740 1741 return (AE_OK); 1742 } 1743 1744 1745 /****************************************************************************** 1746 * 1747 * FUNCTION: DtCompileHest 1748 * 1749 * PARAMETERS: List - Current field list pointer 1750 * 1751 * RETURN: Status 1752 * 1753 * DESCRIPTION: Compile HEST. 1754 * 1755 *****************************************************************************/ 1756 1757 ACPI_STATUS 1758 DtCompileHest ( 1759 void **List) 1760 { 1761 ACPI_STATUS Status; 1762 DT_SUBTABLE *Subtable; 1763 DT_SUBTABLE *ParentTable; 1764 DT_FIELD **PFieldList = (DT_FIELD **) List; 1765 DT_FIELD *SubtableStart; 1766 ACPI_DMTABLE_INFO *InfoTable; 1767 UINT16 Type; 1768 UINT32 BankCount; 1769 1770 1771 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest, 1772 &Subtable); 1773 if (ACPI_FAILURE (Status)) 1774 { 1775 return (Status); 1776 } 1777 1778 ParentTable = DtPeekSubtable (); 1779 DtInsertSubtable (ParentTable, Subtable); 1780 1781 while (*PFieldList) 1782 { 1783 /* Get subtable type */ 1784 1785 SubtableStart = *PFieldList; 1786 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0); 1787 1788 switch (Type) 1789 { 1790 case ACPI_HEST_TYPE_IA32_CHECK: 1791 1792 InfoTable = AcpiDmTableInfoHest0; 1793 break; 1794 1795 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 1796 1797 InfoTable = AcpiDmTableInfoHest1; 1798 break; 1799 1800 case ACPI_HEST_TYPE_IA32_NMI: 1801 1802 InfoTable = AcpiDmTableInfoHest2; 1803 break; 1804 1805 case ACPI_HEST_TYPE_AER_ROOT_PORT: 1806 1807 InfoTable = AcpiDmTableInfoHest6; 1808 break; 1809 1810 case ACPI_HEST_TYPE_AER_ENDPOINT: 1811 1812 InfoTable = AcpiDmTableInfoHest7; 1813 break; 1814 1815 case ACPI_HEST_TYPE_AER_BRIDGE: 1816 1817 InfoTable = AcpiDmTableInfoHest8; 1818 break; 1819 1820 case ACPI_HEST_TYPE_GENERIC_ERROR: 1821 1822 InfoTable = AcpiDmTableInfoHest9; 1823 break; 1824 1825 case ACPI_HEST_TYPE_GENERIC_ERROR_V2: 1826 1827 InfoTable = AcpiDmTableInfoHest10; 1828 break; 1829 1830 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 1831 1832 InfoTable = AcpiDmTableInfoHest11; 1833 break; 1834 1835 default: 1836 1837 /* Cannot continue on unknown type */ 1838 1839 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST"); 1840 return (AE_ERROR); 1841 } 1842 1843 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1844 if (ACPI_FAILURE (Status)) 1845 { 1846 return (Status); 1847 } 1848 1849 DtInsertSubtable (ParentTable, Subtable); 1850 1851 /* 1852 * Additional subtable data - IA32 Error Bank(s) 1853 */ 1854 BankCount = 0; 1855 switch (Type) 1856 { 1857 case ACPI_HEST_TYPE_IA32_CHECK: 1858 1859 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK, 1860 Subtable->Buffer))->NumHardwareBanks; 1861 break; 1862 1863 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 1864 1865 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED, 1866 Subtable->Buffer))->NumHardwareBanks; 1867 break; 1868 1869 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 1870 1871 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK, 1872 Subtable->Buffer))->NumHardwareBanks; 1873 break; 1874 1875 default: 1876 1877 break; 1878 } 1879 1880 while (BankCount) 1881 { 1882 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank, 1883 &Subtable); 1884 if (ACPI_FAILURE (Status)) 1885 { 1886 return (Status); 1887 } 1888 1889 DtInsertSubtable (ParentTable, Subtable); 1890 BankCount--; 1891 } 1892 } 1893 1894 return (AE_OK); 1895 } 1896 1897 1898 /****************************************************************************** 1899 * 1900 * FUNCTION: DtCompileHmat 1901 * 1902 * PARAMETERS: List - Current field list pointer 1903 * 1904 * RETURN: Status 1905 * 1906 * DESCRIPTION: Compile HMAT. 1907 * 1908 *****************************************************************************/ 1909 1910 ACPI_STATUS 1911 DtCompileHmat ( 1912 void **List) 1913 { 1914 ACPI_STATUS Status; 1915 DT_SUBTABLE *Subtable; 1916 DT_SUBTABLE *ParentTable; 1917 DT_FIELD **PFieldList = (DT_FIELD **) List; 1918 DT_FIELD *SubtableStart; 1919 DT_FIELD *EntryStart; 1920 ACPI_HMAT_STRUCTURE *HmatStruct; 1921 ACPI_HMAT_LOCALITY *HmatLocality; 1922 ACPI_HMAT_CACHE *HmatCache; 1923 ACPI_DMTABLE_INFO *InfoTable; 1924 UINT32 IntPDNumber; 1925 UINT32 TgtPDNumber; 1926 UINT64 EntryNumber; 1927 UINT16 SMBIOSHandleNumber; 1928 1929 1930 ParentTable = DtPeekSubtable (); 1931 1932 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat, 1933 &Subtable); 1934 if (ACPI_FAILURE (Status)) 1935 { 1936 return (Status); 1937 } 1938 DtInsertSubtable (ParentTable, Subtable); 1939 1940 while (*PFieldList) 1941 { 1942 /* Compile HMAT structure header */ 1943 1944 SubtableStart = *PFieldList; 1945 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr, 1946 &Subtable); 1947 if (ACPI_FAILURE (Status)) 1948 { 1949 return (Status); 1950 } 1951 DtInsertSubtable (ParentTable, Subtable); 1952 1953 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer); 1954 HmatStruct->Length = Subtable->Length; 1955 1956 /* Compile HMAT structure body */ 1957 1958 switch (HmatStruct->Type) 1959 { 1960 case ACPI_HMAT_TYPE_ADDRESS_RANGE: 1961 1962 InfoTable = AcpiDmTableInfoHmat0; 1963 break; 1964 1965 case ACPI_HMAT_TYPE_LOCALITY: 1966 1967 InfoTable = AcpiDmTableInfoHmat1; 1968 break; 1969 1970 case ACPI_HMAT_TYPE_CACHE: 1971 1972 InfoTable = AcpiDmTableInfoHmat2; 1973 break; 1974 1975 default: 1976 1977 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT"); 1978 return (AE_ERROR); 1979 } 1980 1981 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1982 if (ACPI_FAILURE (Status)) 1983 { 1984 return (Status); 1985 } 1986 DtInsertSubtable (ParentTable, Subtable); 1987 HmatStruct->Length += Subtable->Length; 1988 1989 /* Compile HMAT structure additional */ 1990 1991 switch (HmatStruct->Type) 1992 { 1993 case ACPI_HMAT_TYPE_LOCALITY: 1994 1995 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY, 1996 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 1997 1998 /* Compile initiator proximity domain list */ 1999 2000 IntPDNumber = 0; 2001 while (*PFieldList) 2002 { 2003 Status = DtCompileTable (PFieldList, 2004 AcpiDmTableInfoHmat1a, &Subtable); 2005 if (ACPI_FAILURE (Status)) 2006 { 2007 return (Status); 2008 } 2009 if (!Subtable) 2010 { 2011 break; 2012 } 2013 DtInsertSubtable (ParentTable, Subtable); 2014 HmatStruct->Length += Subtable->Length; 2015 IntPDNumber++; 2016 } 2017 HmatLocality->NumberOfInitiatorPDs = IntPDNumber; 2018 2019 /* Compile target proximity domain list */ 2020 2021 TgtPDNumber = 0; 2022 while (*PFieldList) 2023 { 2024 Status = DtCompileTable (PFieldList, 2025 AcpiDmTableInfoHmat1b, &Subtable); 2026 if (ACPI_FAILURE (Status)) 2027 { 2028 return (Status); 2029 } 2030 if (!Subtable) 2031 { 2032 break; 2033 } 2034 DtInsertSubtable (ParentTable, Subtable); 2035 HmatStruct->Length += Subtable->Length; 2036 TgtPDNumber++; 2037 } 2038 HmatLocality->NumberOfTargetPDs = TgtPDNumber; 2039 2040 /* Save start of the entries for reporting errors */ 2041 2042 EntryStart = *PFieldList; 2043 2044 /* Compile latency/bandwidth entries */ 2045 2046 EntryNumber = 0; 2047 while (*PFieldList) 2048 { 2049 Status = DtCompileTable (PFieldList, 2050 AcpiDmTableInfoHmat1c, &Subtable); 2051 if (ACPI_FAILURE (Status)) 2052 { 2053 return (Status); 2054 } 2055 if (!Subtable) 2056 { 2057 break; 2058 } 2059 DtInsertSubtable (ParentTable, Subtable); 2060 HmatStruct->Length += Subtable->Length; 2061 EntryNumber++; 2062 } 2063 2064 /* Validate number of entries */ 2065 2066 if (EntryNumber != 2067 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber)) 2068 { 2069 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT"); 2070 return (AE_ERROR); 2071 } 2072 break; 2073 2074 case ACPI_HMAT_TYPE_CACHE: 2075 2076 /* Compile SMBIOS handles */ 2077 2078 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE, 2079 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 2080 SMBIOSHandleNumber = 0; 2081 while (*PFieldList) 2082 { 2083 Status = DtCompileTable (PFieldList, 2084 AcpiDmTableInfoHmat2a, &Subtable); 2085 if (ACPI_FAILURE (Status)) 2086 { 2087 return (Status); 2088 } 2089 if (!Subtable) 2090 { 2091 break; 2092 } 2093 DtInsertSubtable (ParentTable, Subtable); 2094 HmatStruct->Length += Subtable->Length; 2095 SMBIOSHandleNumber++; 2096 } 2097 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber; 2098 break; 2099 2100 default: 2101 2102 break; 2103 } 2104 } 2105 2106 return (AE_OK); 2107 } 2108 2109 2110 /****************************************************************************** 2111 * 2112 * FUNCTION: DtCompileIort 2113 * 2114 * PARAMETERS: List - Current field list pointer 2115 * 2116 * RETURN: Status 2117 * 2118 * DESCRIPTION: Compile IORT. 2119 * 2120 *****************************************************************************/ 2121 2122 ACPI_STATUS 2123 DtCompileIort ( 2124 void **List) 2125 { 2126 ACPI_STATUS Status; 2127 DT_SUBTABLE *Subtable; 2128 DT_SUBTABLE *ParentTable; 2129 DT_FIELD **PFieldList = (DT_FIELD **) List; 2130 DT_FIELD *SubtableStart; 2131 ACPI_TABLE_HEADER *Table; 2132 ACPI_TABLE_IORT *Iort; 2133 ACPI_IORT_NODE *IortNode; 2134 ACPI_IORT_ITS_GROUP *IortItsGroup; 2135 ACPI_IORT_SMMU *IortSmmu; 2136 ACPI_IORT_RMR *IortRmr; 2137 UINT32 NodeNumber; 2138 UINT32 NodeLength; 2139 UINT32 IdMappingNumber; 2140 UINT32 ItsNumber; 2141 UINT32 ContextIrptNumber; 2142 UINT32 PmuIrptNumber; 2143 UINT32 PaddingLength; 2144 UINT8 Revision; 2145 UINT32 RmrCount; 2146 2147 2148 ParentTable = DtPeekSubtable (); 2149 2150 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort, 2151 &Subtable); 2152 if (ACPI_FAILURE (Status)) 2153 { 2154 return (Status); 2155 } 2156 DtInsertSubtable (ParentTable, Subtable); 2157 2158 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 2159 Revision = Table->Revision; 2160 2161 /* IORT Revisions E, E.a & E.c have known issues and are not supported */ 2162 2163 if (Revision == 1 || Revision == 2 || Revision == 4) 2164 { 2165 DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision"); 2166 return (AE_ERROR); 2167 } 2168 2169 /* 2170 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 2171 * should be taken to avoid accessing ACPI_TABLE_HEADER fields. 2172 */ 2173 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT, 2174 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 2175 2176 /* 2177 * OptionalPadding - Variable-length data 2178 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT)) 2179 * Optionally allows the generic data types to be used for filling 2180 * this field. 2181 */ 2182 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT); 2183 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad, 2184 &Subtable); 2185 if (ACPI_FAILURE (Status)) 2186 { 2187 return (Status); 2188 } 2189 if (Subtable) 2190 { 2191 DtInsertSubtable (ParentTable, Subtable); 2192 Iort->NodeOffset += Subtable->Length; 2193 } 2194 else 2195 { 2196 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList), 2197 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength); 2198 if (ACPI_FAILURE (Status)) 2199 { 2200 return (Status); 2201 } 2202 Iort->NodeOffset += PaddingLength; 2203 } 2204 2205 NodeNumber = 0; 2206 while (*PFieldList) 2207 { 2208 SubtableStart = *PFieldList; 2209 if (Revision == 0) 2210 { 2211 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr, 2212 &Subtable); 2213 } 2214 else if (Revision >= 3) 2215 { 2216 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3, 2217 &Subtable); 2218 } 2219 2220 if (ACPI_FAILURE (Status)) 2221 { 2222 return (Status); 2223 } 2224 2225 DtInsertSubtable (ParentTable, Subtable); 2226 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer); 2227 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData); 2228 2229 DtPushSubtable (Subtable); 2230 ParentTable = DtPeekSubtable (); 2231 2232 switch (IortNode->Type) 2233 { 2234 case ACPI_IORT_NODE_ITS_GROUP: 2235 2236 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0, 2237 &Subtable); 2238 if (ACPI_FAILURE (Status)) 2239 { 2240 return (Status); 2241 } 2242 2243 DtInsertSubtable (ParentTable, Subtable); 2244 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer); 2245 NodeLength += Subtable->Length; 2246 2247 ItsNumber = 0; 2248 while (*PFieldList) 2249 { 2250 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a, 2251 &Subtable); 2252 if (ACPI_FAILURE (Status)) 2253 { 2254 return (Status); 2255 } 2256 if (!Subtable) 2257 { 2258 break; 2259 } 2260 2261 DtInsertSubtable (ParentTable, Subtable); 2262 NodeLength += Subtable->Length; 2263 ItsNumber++; 2264 } 2265 2266 IortItsGroup->ItsCount = ItsNumber; 2267 break; 2268 2269 case ACPI_IORT_NODE_NAMED_COMPONENT: 2270 2271 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1, 2272 &Subtable); 2273 if (ACPI_FAILURE (Status)) 2274 { 2275 return (Status); 2276 } 2277 2278 DtInsertSubtable (ParentTable, Subtable); 2279 NodeLength += Subtable->Length; 2280 2281 /* 2282 * Padding - Variable-length data 2283 * Optionally allows the offset of the ID mappings to be used 2284 * for filling this field. 2285 */ 2286 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a, 2287 &Subtable); 2288 if (ACPI_FAILURE (Status)) 2289 { 2290 return (Status); 2291 } 2292 2293 if (Subtable) 2294 { 2295 DtInsertSubtable (ParentTable, Subtable); 2296 NodeLength += Subtable->Length; 2297 } 2298 else 2299 { 2300 if (NodeLength > IortNode->MappingOffset) 2301 { 2302 return (AE_BAD_DATA); 2303 } 2304 2305 if (NodeLength < IortNode->MappingOffset) 2306 { 2307 Status = DtCompilePadding ( 2308 IortNode->MappingOffset - NodeLength, 2309 &Subtable); 2310 if (ACPI_FAILURE (Status)) 2311 { 2312 return (Status); 2313 } 2314 2315 DtInsertSubtable (ParentTable, Subtable); 2316 NodeLength = IortNode->MappingOffset; 2317 } 2318 } 2319 break; 2320 2321 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX: 2322 2323 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2, 2324 &Subtable); 2325 if (ACPI_FAILURE (Status)) 2326 { 2327 return (Status); 2328 } 2329 2330 DtInsertSubtable (ParentTable, Subtable); 2331 NodeLength += Subtable->Length; 2332 break; 2333 2334 case ACPI_IORT_NODE_SMMU: 2335 2336 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3, 2337 &Subtable); 2338 if (ACPI_FAILURE (Status)) 2339 { 2340 return (Status); 2341 } 2342 2343 DtInsertSubtable (ParentTable, Subtable); 2344 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer); 2345 NodeLength += Subtable->Length; 2346 2347 /* Compile global interrupt array */ 2348 2349 IortSmmu->GlobalInterruptOffset = NodeLength; 2350 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a, 2351 &Subtable); 2352 if (ACPI_FAILURE (Status)) 2353 { 2354 return (Status); 2355 } 2356 2357 DtInsertSubtable (ParentTable, Subtable); 2358 NodeLength += Subtable->Length; 2359 2360 /* Compile context interrupt array */ 2361 2362 ContextIrptNumber = 0; 2363 IortSmmu->ContextInterruptOffset = NodeLength; 2364 while (*PFieldList) 2365 { 2366 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b, 2367 &Subtable); 2368 if (ACPI_FAILURE (Status)) 2369 { 2370 return (Status); 2371 } 2372 2373 if (!Subtable) 2374 { 2375 break; 2376 } 2377 2378 DtInsertSubtable (ParentTable, Subtable); 2379 NodeLength += Subtable->Length; 2380 ContextIrptNumber++; 2381 } 2382 2383 IortSmmu->ContextInterruptCount = ContextIrptNumber; 2384 2385 /* Compile PMU interrupt array */ 2386 2387 PmuIrptNumber = 0; 2388 IortSmmu->PmuInterruptOffset = NodeLength; 2389 while (*PFieldList) 2390 { 2391 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c, 2392 &Subtable); 2393 if (ACPI_FAILURE (Status)) 2394 { 2395 return (Status); 2396 } 2397 2398 if (!Subtable) 2399 { 2400 break; 2401 } 2402 2403 DtInsertSubtable (ParentTable, Subtable); 2404 NodeLength += Subtable->Length; 2405 PmuIrptNumber++; 2406 } 2407 2408 IortSmmu->PmuInterruptCount = PmuIrptNumber; 2409 break; 2410 2411 case ACPI_IORT_NODE_SMMU_V3: 2412 2413 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4, 2414 &Subtable); 2415 if (ACPI_FAILURE (Status)) 2416 { 2417 return (Status); 2418 } 2419 2420 DtInsertSubtable (ParentTable, Subtable); 2421 NodeLength += Subtable->Length; 2422 break; 2423 2424 case ACPI_IORT_NODE_PMCG: 2425 2426 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5, 2427 &Subtable); 2428 if (ACPI_FAILURE (Status)) 2429 { 2430 return (Status); 2431 } 2432 2433 DtInsertSubtable (ParentTable, Subtable); 2434 NodeLength += Subtable->Length; 2435 break; 2436 2437 case ACPI_IORT_NODE_RMR: 2438 2439 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6, 2440 &Subtable); 2441 if (ACPI_FAILURE (Status)) 2442 { 2443 return (Status); 2444 } 2445 2446 DtInsertSubtable (ParentTable, Subtable); 2447 IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer); 2448 NodeLength += Subtable->Length; 2449 2450 /* Compile RMR Descriptors */ 2451 2452 RmrCount = 0; 2453 IortRmr->RmrOffset = NodeLength; 2454 while (*PFieldList) 2455 { 2456 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a, 2457 &Subtable); 2458 if (ACPI_FAILURE (Status)) 2459 { 2460 return (Status); 2461 } 2462 2463 if (!Subtable) 2464 { 2465 break; 2466 } 2467 2468 DtInsertSubtable (ParentTable, Subtable); 2469 NodeLength += sizeof (ACPI_IORT_RMR_DESC); 2470 RmrCount++; 2471 } 2472 2473 IortRmr->RmrCount = RmrCount; 2474 break; 2475 2476 default: 2477 2478 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT"); 2479 return (AE_ERROR); 2480 } 2481 2482 /* Compile Array of ID mappings */ 2483 2484 IortNode->MappingOffset = NodeLength; 2485 IdMappingNumber = 0; 2486 while (*PFieldList) 2487 { 2488 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap, 2489 &Subtable); 2490 if (ACPI_FAILURE (Status)) 2491 { 2492 return (Status); 2493 } 2494 2495 if (!Subtable) 2496 { 2497 break; 2498 } 2499 2500 DtInsertSubtable (ParentTable, Subtable); 2501 NodeLength += sizeof (ACPI_IORT_ID_MAPPING); 2502 IdMappingNumber++; 2503 } 2504 2505 IortNode->MappingCount = IdMappingNumber; 2506 if (!IdMappingNumber) 2507 { 2508 IortNode->MappingOffset = 0; 2509 } 2510 2511 /* 2512 * Node length can be determined by DT_LENGTH option 2513 * IortNode->Length = NodeLength; 2514 */ 2515 DtPopSubtable (); 2516 ParentTable = DtPeekSubtable (); 2517 NodeNumber++; 2518 } 2519 2520 Iort->NodeCount = NodeNumber; 2521 return (AE_OK); 2522 } 2523 2524 2525 /****************************************************************************** 2526 * 2527 * FUNCTION: DtCompileIvrs 2528 * 2529 * PARAMETERS: List - Current field list pointer 2530 * 2531 * RETURN: Status 2532 * 2533 * DESCRIPTION: Compile IVRS. Notes: 2534 * The IVRS is essentially a flat table, with the following 2535 * structure: 2536 * <Main ACPI Table Header> 2537 * <Main subtable - virtualization info> 2538 * <IVHD> 2539 * <Device Entries> 2540 * ... 2541 * <IVHD> 2542 * <Device Entries> 2543 * <IVMD> 2544 * ... 2545 * 2546 *****************************************************************************/ 2547 2548 ACPI_STATUS 2549 DtCompileIvrs ( 2550 void **List) 2551 { 2552 ACPI_STATUS Status; 2553 DT_SUBTABLE *Subtable; 2554 DT_SUBTABLE *ParentTable; 2555 DT_SUBTABLE *MainSubtable; 2556 DT_FIELD **PFieldList = (DT_FIELD **) List; 2557 DT_FIELD *SubtableStart; 2558 ACPI_DMTABLE_INFO *InfoTable = NULL; 2559 UINT8 SubtableType; 2560 UINT8 Temp64[16]; 2561 UINT8 Temp8; 2562 2563 2564 /* Main table */ 2565 2566 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs, 2567 &Subtable); 2568 if (ACPI_FAILURE (Status)) 2569 { 2570 return (Status); 2571 } 2572 2573 ParentTable = DtPeekSubtable (); 2574 DtInsertSubtable (ParentTable, Subtable); 2575 DtPushSubtable (Subtable); 2576 2577 /* Save a pointer to the main subtable */ 2578 2579 MainSubtable = Subtable; 2580 2581 while (*PFieldList) 2582 { 2583 SubtableStart = *PFieldList; 2584 2585 /* Compile the SubtableType integer */ 2586 2587 DtCompileInteger (&SubtableType, *PFieldList, 1, 0); 2588 2589 switch (SubtableType) 2590 { 2591 2592 /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */ 2593 2594 case ACPI_IVRS_TYPE_HARDWARE1: 2595 2596 InfoTable = AcpiDmTableInfoIvrsHware1; 2597 break; 2598 2599 /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */ 2600 2601 case ACPI_IVRS_TYPE_HARDWARE2: 2602 case ACPI_IVRS_TYPE_HARDWARE3: 2603 2604 InfoTable = AcpiDmTableInfoIvrsHware23; 2605 break; 2606 2607 /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */ 2608 2609 case ACPI_IVRS_TYPE_MEMORY1: 2610 case ACPI_IVRS_TYPE_MEMORY2: 2611 case ACPI_IVRS_TYPE_MEMORY3: 2612 2613 InfoTable = AcpiDmTableInfoIvrsMemory; 2614 break; 2615 2616 /* 4-byte device entries */ 2617 2618 case ACPI_IVRS_TYPE_PAD4: 2619 case ACPI_IVRS_TYPE_ALL: 2620 case ACPI_IVRS_TYPE_SELECT: 2621 case ACPI_IVRS_TYPE_START: 2622 case ACPI_IVRS_TYPE_END: 2623 2624 InfoTable = AcpiDmTableInfoIvrs4; 2625 break; 2626 2627 /* 8-byte device entries, type A */ 2628 2629 case ACPI_IVRS_TYPE_ALIAS_SELECT: 2630 case ACPI_IVRS_TYPE_ALIAS_START: 2631 2632 InfoTable = AcpiDmTableInfoIvrs8a; 2633 break; 2634 2635 /* 8-byte device entries, type B */ 2636 2637 case ACPI_IVRS_TYPE_EXT_SELECT: 2638 case ACPI_IVRS_TYPE_EXT_START: 2639 2640 InfoTable = AcpiDmTableInfoIvrs8b; 2641 break; 2642 2643 /* 8-byte device entries, type C */ 2644 2645 case ACPI_IVRS_TYPE_SPECIAL: 2646 2647 InfoTable = AcpiDmTableInfoIvrs8c; 2648 break; 2649 2650 /* Variable device entries, type F0h */ 2651 2652 case ACPI_IVRS_TYPE_HID: 2653 2654 InfoTable = AcpiDmTableInfoIvrsHid; 2655 break; 2656 2657 default: 2658 2659 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, 2660 "IVRS Device Entry"); 2661 return (AE_ERROR); 2662 } 2663 2664 /* Compile the InfoTable from above */ 2665 2666 Status = DtCompileTable (PFieldList, InfoTable, 2667 &Subtable); 2668 if (ACPI_FAILURE (Status)) 2669 { 2670 return (Status); 2671 } 2672 2673 ParentTable = DtPeekSubtable (); 2674 if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 && 2675 SubtableType != ACPI_IVRS_TYPE_HARDWARE2 && 2676 SubtableType != ACPI_IVRS_TYPE_HARDWARE3 && 2677 SubtableType != ACPI_IVRS_TYPE_HID && 2678 SubtableType != ACPI_IVRS_TYPE_MEMORY1 && 2679 SubtableType != ACPI_IVRS_TYPE_MEMORY2 && 2680 SubtableType != ACPI_IVRS_TYPE_MEMORY3) 2681 { 2682 if (ParentTable) 2683 DtInsertSubtable (ParentTable, Subtable); 2684 } 2685 2686 switch (SubtableType) 2687 { 2688 case ACPI_IVRS_TYPE_HARDWARE1: 2689 case ACPI_IVRS_TYPE_HARDWARE2: 2690 case ACPI_IVRS_TYPE_HARDWARE3: 2691 case ACPI_IVRS_TYPE_MEMORY1: 2692 case ACPI_IVRS_TYPE_MEMORY2: 2693 case ACPI_IVRS_TYPE_MEMORY3: 2694 2695 /* Insert these IVHDs/IVMDs at the root subtable */ 2696 2697 DtInsertSubtable (MainSubtable, Subtable); 2698 DtPushSubtable (Subtable); 2699 break; 2700 2701 case ACPI_IVRS_TYPE_HID: 2702 2703 /* Special handling for the HID named device entry (0xF0) */ 2704 2705 if (ParentTable) 2706 { 2707 DtInsertSubtable (ParentTable, Subtable); 2708 } 2709 2710 /* 2711 * Process the HID value. First, get the HID value as a string. 2712 */ 2713 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); 2714 2715 /* 2716 * Determine if the HID is an integer or a string. 2717 * An integer is defined to be 32 bits, with the upper 32 bits 2718 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit 2719 * integer or a character string. If an integer, the lower 2720 * 4 bytes of the field contain the integer and the upper 2721 * 4 bytes are padded with 0". 2722 */ 2723 if (UtIsIdInteger ((UINT8 *) &Temp64)) 2724 { 2725 /* Compile the HID value as an integer */ 2726 2727 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); 2728 2729 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger, 2730 &Subtable); 2731 if (ACPI_FAILURE (Status)) 2732 { 2733 return (Status); 2734 } 2735 } 2736 else 2737 { 2738 /* Compile the HID value as a string */ 2739 2740 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString, 2741 &Subtable); 2742 if (ACPI_FAILURE (Status)) 2743 { 2744 return (Status); 2745 } 2746 } 2747 2748 DtInsertSubtable (ParentTable, Subtable); 2749 2750 /* 2751 * Process the CID value. First, get the CID value as a string. 2752 */ 2753 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); 2754 2755 if (UtIsIdInteger ((UINT8 *) &Temp64)) 2756 { 2757 /* Compile the CID value as an integer */ 2758 2759 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); 2760 2761 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger, 2762 &Subtable); 2763 if (ACPI_FAILURE (Status)) 2764 { 2765 return (Status); 2766 } 2767 } 2768 else 2769 { 2770 /* Compile the CID value as a string */ 2771 2772 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString, 2773 &Subtable); 2774 if (ACPI_FAILURE (Status)) 2775 { 2776 return (Status); 2777 } 2778 } 2779 2780 DtInsertSubtable (ParentTable, Subtable); 2781 2782 /* 2783 * Process the UID value. First, get and decode the "UID Format" field (Integer). 2784 */ 2785 if (!*PFieldList) 2786 { 2787 return (AE_OK); 2788 } 2789 2790 DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0); 2791 2792 switch (Temp8) 2793 { 2794 case ACPI_IVRS_UID_NOT_PRESENT: 2795 break; 2796 2797 case ACPI_IVRS_UID_IS_INTEGER: 2798 2799 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger, 2800 &Subtable); 2801 if (ACPI_FAILURE (Status)) 2802 { 2803 return (Status); 2804 } 2805 DtInsertSubtable (ParentTable, Subtable); 2806 break; 2807 2808 case ACPI_IVRS_UID_IS_STRING: 2809 2810 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString, 2811 &Subtable); 2812 if (ACPI_FAILURE (Status)) 2813 { 2814 return (Status); 2815 } 2816 DtInsertSubtable (ParentTable, Subtable); 2817 break; 2818 2819 default: 2820 2821 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart, 2822 "IVRS Device Entry"); 2823 return (AE_ERROR); 2824 } 2825 2826 default: 2827 2828 /* All other subtable types come through here */ 2829 break; 2830 } 2831 } 2832 2833 return (AE_OK); 2834 } 2835