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 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 default: 1403 1404 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR"); 1405 return (AE_ERROR); 1406 } 1407 1408 /* DMAR Subtable */ 1409 1410 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1411 if (ACPI_FAILURE (Status)) 1412 { 1413 return (Status); 1414 } 1415 1416 ParentTable = DtPeekSubtable (); 1417 DtInsertSubtable (ParentTable, Subtable); 1418 1419 /* 1420 * Optional Device Scope subtables 1421 */ 1422 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) || 1423 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE)) 1424 { 1425 /* These types do not support device scopes */ 1426 1427 DtPopSubtable (); 1428 continue; 1429 } 1430 1431 DtPushSubtable (Subtable); 1432 DeviceScopeLength = DmarHeader->Length - Subtable->Length - 1433 ParentTable->Length; 1434 while (DeviceScopeLength) 1435 { 1436 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope, 1437 &Subtable); 1438 if (Status == AE_NOT_FOUND) 1439 { 1440 break; 1441 } 1442 1443 ParentTable = DtPeekSubtable (); 1444 DtInsertSubtable (ParentTable, Subtable); 1445 DtPushSubtable (Subtable); 1446 1447 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer); 1448 1449 /* Optional PCI Paths */ 1450 1451 PciPathLength = DmarDeviceScope->Length - Subtable->Length; 1452 while (PciPathLength) 1453 { 1454 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath, 1455 &Subtable); 1456 if (Status == AE_NOT_FOUND) 1457 { 1458 DtPopSubtable (); 1459 break; 1460 } 1461 1462 ParentTable = DtPeekSubtable (); 1463 DtInsertSubtable (ParentTable, Subtable); 1464 PciPathLength -= Subtable->Length; 1465 } 1466 1467 DtPopSubtable (); 1468 DeviceScopeLength -= DmarDeviceScope->Length; 1469 } 1470 1471 DtPopSubtable (); 1472 DtPopSubtable (); 1473 } 1474 1475 return (AE_OK); 1476 } 1477 1478 1479 /****************************************************************************** 1480 * 1481 * FUNCTION: DtCompileDrtm 1482 * 1483 * PARAMETERS: List - Current field list pointer 1484 * 1485 * RETURN: Status 1486 * 1487 * DESCRIPTION: Compile DRTM. 1488 * 1489 *****************************************************************************/ 1490 1491 ACPI_STATUS 1492 DtCompileDrtm ( 1493 void **List) 1494 { 1495 ACPI_STATUS Status; 1496 DT_SUBTABLE *Subtable; 1497 DT_SUBTABLE *ParentTable; 1498 DT_FIELD **PFieldList = (DT_FIELD **) List; 1499 UINT32 Count; 1500 /* ACPI_TABLE_DRTM *Drtm; */ 1501 ACPI_DRTM_VTABLE_LIST *DrtmVtl; 1502 ACPI_DRTM_RESOURCE_LIST *DrtmRl; 1503 /* ACPI_DRTM_DPS_ID *DrtmDps; */ 1504 1505 1506 ParentTable = DtPeekSubtable (); 1507 1508 /* Compile DRTM header */ 1509 1510 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm, 1511 &Subtable); 1512 if (ACPI_FAILURE (Status)) 1513 { 1514 return (Status); 1515 } 1516 DtInsertSubtable (ParentTable, Subtable); 1517 1518 /* 1519 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 1520 * should be taken to avoid accessing ACPI_TABLE_HADER fields. 1521 */ 1522 #if 0 1523 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM, 1524 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 1525 #endif 1526 /* Compile VTL */ 1527 1528 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0, 1529 &Subtable); 1530 if (ACPI_FAILURE (Status)) 1531 { 1532 return (Status); 1533 } 1534 1535 DtInsertSubtable (ParentTable, Subtable); 1536 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer); 1537 1538 DtPushSubtable (Subtable); 1539 ParentTable = DtPeekSubtable (); 1540 Count = 0; 1541 1542 while (*PFieldList) 1543 { 1544 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a, 1545 &Subtable); 1546 if (ACPI_FAILURE (Status)) 1547 { 1548 return (Status); 1549 } 1550 if (!Subtable) 1551 { 1552 break; 1553 } 1554 DtInsertSubtable (ParentTable, Subtable); 1555 Count++; 1556 } 1557 1558 DrtmVtl->ValidatedTableCount = Count; 1559 DtPopSubtable (); 1560 ParentTable = DtPeekSubtable (); 1561 1562 /* Compile RL */ 1563 1564 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1, 1565 &Subtable); 1566 if (ACPI_FAILURE (Status)) 1567 { 1568 return (Status); 1569 } 1570 1571 DtInsertSubtable (ParentTable, Subtable); 1572 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer); 1573 1574 DtPushSubtable (Subtable); 1575 ParentTable = DtPeekSubtable (); 1576 Count = 0; 1577 1578 while (*PFieldList) 1579 { 1580 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a, 1581 &Subtable); 1582 if (ACPI_FAILURE (Status)) 1583 { 1584 return (Status); 1585 } 1586 1587 if (!Subtable) 1588 { 1589 break; 1590 } 1591 1592 DtInsertSubtable (ParentTable, Subtable); 1593 Count++; 1594 } 1595 1596 DrtmRl->ResourceCount = Count; 1597 DtPopSubtable (); 1598 ParentTable = DtPeekSubtable (); 1599 1600 /* Compile DPS */ 1601 1602 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2, 1603 &Subtable); 1604 if (ACPI_FAILURE (Status)) 1605 { 1606 return (Status); 1607 } 1608 DtInsertSubtable (ParentTable, Subtable); 1609 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/ 1610 1611 1612 return (AE_OK); 1613 } 1614 1615 1616 /****************************************************************************** 1617 * 1618 * FUNCTION: DtCompileEinj 1619 * 1620 * PARAMETERS: List - Current field list pointer 1621 * 1622 * RETURN: Status 1623 * 1624 * DESCRIPTION: Compile EINJ. 1625 * 1626 *****************************************************************************/ 1627 1628 ACPI_STATUS 1629 DtCompileEinj ( 1630 void **List) 1631 { 1632 ACPI_STATUS Status; 1633 1634 1635 Status = DtCompileTwoSubtables (List, 1636 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0); 1637 return (Status); 1638 } 1639 1640 1641 /****************************************************************************** 1642 * 1643 * FUNCTION: DtCompileErst 1644 * 1645 * PARAMETERS: List - Current field list pointer 1646 * 1647 * RETURN: Status 1648 * 1649 * DESCRIPTION: Compile ERST. 1650 * 1651 *****************************************************************************/ 1652 1653 ACPI_STATUS 1654 DtCompileErst ( 1655 void **List) 1656 { 1657 ACPI_STATUS Status; 1658 1659 1660 Status = DtCompileTwoSubtables (List, 1661 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0); 1662 return (Status); 1663 } 1664 1665 1666 /****************************************************************************** 1667 * 1668 * FUNCTION: DtCompileGtdt 1669 * 1670 * PARAMETERS: List - Current field list pointer 1671 * 1672 * RETURN: Status 1673 * 1674 * DESCRIPTION: Compile GTDT. 1675 * 1676 *****************************************************************************/ 1677 1678 ACPI_STATUS 1679 DtCompileGtdt ( 1680 void **List) 1681 { 1682 ACPI_STATUS Status; 1683 DT_SUBTABLE *Subtable; 1684 DT_SUBTABLE *ParentTable; 1685 DT_FIELD **PFieldList = (DT_FIELD **) List; 1686 DT_FIELD *SubtableStart; 1687 ACPI_SUBTABLE_HEADER *GtdtHeader; 1688 ACPI_DMTABLE_INFO *InfoTable; 1689 UINT32 GtCount; 1690 ACPI_TABLE_HEADER *Header; 1691 1692 1693 ParentTable = DtPeekSubtable (); 1694 1695 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 1696 1697 /* Compile the main table */ 1698 1699 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt, 1700 &Subtable); 1701 if (ACPI_FAILURE (Status)) 1702 { 1703 return (Status); 1704 } 1705 1706 /* GTDT revision 3 later contains 2 extra fields before subtables */ 1707 1708 if (Header->Revision > 2) 1709 { 1710 ParentTable = DtPeekSubtable (); 1711 DtInsertSubtable (ParentTable, Subtable); 1712 1713 Status = DtCompileTable (PFieldList, 1714 AcpiDmTableInfoGtdtEl2, &Subtable); 1715 if (ACPI_FAILURE (Status)) 1716 { 1717 return (Status); 1718 } 1719 } 1720 1721 ParentTable = DtPeekSubtable (); 1722 DtInsertSubtable (ParentTable, Subtable); 1723 1724 while (*PFieldList) 1725 { 1726 SubtableStart = *PFieldList; 1727 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr, 1728 &Subtable); 1729 if (ACPI_FAILURE (Status)) 1730 { 1731 return (Status); 1732 } 1733 1734 ParentTable = DtPeekSubtable (); 1735 DtInsertSubtable (ParentTable, Subtable); 1736 DtPushSubtable (Subtable); 1737 1738 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer); 1739 1740 switch (GtdtHeader->Type) 1741 { 1742 case ACPI_GTDT_TYPE_TIMER_BLOCK: 1743 1744 InfoTable = AcpiDmTableInfoGtdt0; 1745 break; 1746 1747 case ACPI_GTDT_TYPE_WATCHDOG: 1748 1749 InfoTable = AcpiDmTableInfoGtdt1; 1750 break; 1751 1752 default: 1753 1754 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT"); 1755 return (AE_ERROR); 1756 } 1757 1758 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1759 if (ACPI_FAILURE (Status)) 1760 { 1761 return (Status); 1762 } 1763 1764 ParentTable = DtPeekSubtable (); 1765 DtInsertSubtable (ParentTable, Subtable); 1766 1767 /* 1768 * Additional GT block subtable data 1769 */ 1770 1771 switch (GtdtHeader->Type) 1772 { 1773 case ACPI_GTDT_TYPE_TIMER_BLOCK: 1774 1775 DtPushSubtable (Subtable); 1776 ParentTable = DtPeekSubtable (); 1777 1778 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK, 1779 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount; 1780 1781 while (GtCount) 1782 { 1783 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a, 1784 &Subtable); 1785 if (ACPI_FAILURE (Status)) 1786 { 1787 return (Status); 1788 } 1789 1790 DtInsertSubtable (ParentTable, Subtable); 1791 GtCount--; 1792 } 1793 1794 DtPopSubtable (); 1795 break; 1796 1797 default: 1798 1799 break; 1800 } 1801 1802 DtPopSubtable (); 1803 } 1804 1805 return (AE_OK); 1806 } 1807 1808 1809 /****************************************************************************** 1810 * 1811 * FUNCTION: DtCompileFpdt 1812 * 1813 * PARAMETERS: List - Current field list pointer 1814 * 1815 * RETURN: Status 1816 * 1817 * DESCRIPTION: Compile FPDT. 1818 * 1819 *****************************************************************************/ 1820 1821 ACPI_STATUS 1822 DtCompileFpdt ( 1823 void **List) 1824 { 1825 ACPI_STATUS Status; 1826 ACPI_FPDT_HEADER *FpdtHeader; 1827 DT_SUBTABLE *Subtable; 1828 DT_SUBTABLE *ParentTable; 1829 ACPI_DMTABLE_INFO *InfoTable; 1830 DT_FIELD **PFieldList = (DT_FIELD **) List; 1831 DT_FIELD *SubtableStart; 1832 1833 1834 while (*PFieldList) 1835 { 1836 SubtableStart = *PFieldList; 1837 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr, 1838 &Subtable); 1839 if (ACPI_FAILURE (Status)) 1840 { 1841 return (Status); 1842 } 1843 1844 ParentTable = DtPeekSubtable (); 1845 DtInsertSubtable (ParentTable, Subtable); 1846 DtPushSubtable (Subtable); 1847 1848 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer); 1849 1850 switch (FpdtHeader->Type) 1851 { 1852 case ACPI_FPDT_TYPE_BOOT: 1853 1854 InfoTable = AcpiDmTableInfoFpdt0; 1855 break; 1856 1857 case ACPI_FPDT_TYPE_S3PERF: 1858 1859 InfoTable = AcpiDmTableInfoFpdt1; 1860 break; 1861 1862 default: 1863 1864 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT"); 1865 return (AE_ERROR); 1866 break; 1867 } 1868 1869 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1870 if (ACPI_FAILURE (Status)) 1871 { 1872 return (Status); 1873 } 1874 1875 ParentTable = DtPeekSubtable (); 1876 DtInsertSubtable (ParentTable, Subtable); 1877 DtPopSubtable (); 1878 } 1879 1880 return (AE_OK); 1881 } 1882 1883 1884 /****************************************************************************** 1885 * 1886 * FUNCTION: DtCompileHest 1887 * 1888 * PARAMETERS: List - Current field list pointer 1889 * 1890 * RETURN: Status 1891 * 1892 * DESCRIPTION: Compile HEST. 1893 * 1894 *****************************************************************************/ 1895 1896 ACPI_STATUS 1897 DtCompileHest ( 1898 void **List) 1899 { 1900 ACPI_STATUS Status; 1901 DT_SUBTABLE *Subtable; 1902 DT_SUBTABLE *ParentTable; 1903 DT_FIELD **PFieldList = (DT_FIELD **) List; 1904 DT_FIELD *SubtableStart; 1905 ACPI_DMTABLE_INFO *InfoTable; 1906 UINT16 Type; 1907 UINT32 BankCount; 1908 1909 1910 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest, 1911 &Subtable); 1912 if (ACPI_FAILURE (Status)) 1913 { 1914 return (Status); 1915 } 1916 1917 ParentTable = DtPeekSubtable (); 1918 DtInsertSubtable (ParentTable, Subtable); 1919 1920 while (*PFieldList) 1921 { 1922 /* Get subtable type */ 1923 1924 SubtableStart = *PFieldList; 1925 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0); 1926 1927 switch (Type) 1928 { 1929 case ACPI_HEST_TYPE_IA32_CHECK: 1930 1931 InfoTable = AcpiDmTableInfoHest0; 1932 break; 1933 1934 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 1935 1936 InfoTable = AcpiDmTableInfoHest1; 1937 break; 1938 1939 case ACPI_HEST_TYPE_IA32_NMI: 1940 1941 InfoTable = AcpiDmTableInfoHest2; 1942 break; 1943 1944 case ACPI_HEST_TYPE_AER_ROOT_PORT: 1945 1946 InfoTable = AcpiDmTableInfoHest6; 1947 break; 1948 1949 case ACPI_HEST_TYPE_AER_ENDPOINT: 1950 1951 InfoTable = AcpiDmTableInfoHest7; 1952 break; 1953 1954 case ACPI_HEST_TYPE_AER_BRIDGE: 1955 1956 InfoTable = AcpiDmTableInfoHest8; 1957 break; 1958 1959 case ACPI_HEST_TYPE_GENERIC_ERROR: 1960 1961 InfoTable = AcpiDmTableInfoHest9; 1962 break; 1963 1964 case ACPI_HEST_TYPE_GENERIC_ERROR_V2: 1965 1966 InfoTable = AcpiDmTableInfoHest10; 1967 break; 1968 1969 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 1970 1971 InfoTable = AcpiDmTableInfoHest11; 1972 break; 1973 1974 default: 1975 1976 /* Cannot continue on unknown type */ 1977 1978 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST"); 1979 return (AE_ERROR); 1980 } 1981 1982 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1983 if (ACPI_FAILURE (Status)) 1984 { 1985 return (Status); 1986 } 1987 1988 DtInsertSubtable (ParentTable, Subtable); 1989 1990 /* 1991 * Additional subtable data - IA32 Error Bank(s) 1992 */ 1993 BankCount = 0; 1994 switch (Type) 1995 { 1996 case ACPI_HEST_TYPE_IA32_CHECK: 1997 1998 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK, 1999 Subtable->Buffer))->NumHardwareBanks; 2000 break; 2001 2002 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 2003 2004 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED, 2005 Subtable->Buffer))->NumHardwareBanks; 2006 break; 2007 2008 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 2009 2010 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK, 2011 Subtable->Buffer))->NumHardwareBanks; 2012 break; 2013 2014 default: 2015 2016 break; 2017 } 2018 2019 while (BankCount) 2020 { 2021 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank, 2022 &Subtable); 2023 if (ACPI_FAILURE (Status)) 2024 { 2025 return (Status); 2026 } 2027 2028 DtInsertSubtable (ParentTable, Subtable); 2029 BankCount--; 2030 } 2031 } 2032 2033 return (AE_OK); 2034 } 2035 2036 2037 /****************************************************************************** 2038 * 2039 * FUNCTION: DtCompileHmat 2040 * 2041 * PARAMETERS: List - Current field list pointer 2042 * 2043 * RETURN: Status 2044 * 2045 * DESCRIPTION: Compile HMAT. 2046 * 2047 *****************************************************************************/ 2048 2049 ACPI_STATUS 2050 DtCompileHmat ( 2051 void **List) 2052 { 2053 ACPI_STATUS Status; 2054 DT_SUBTABLE *Subtable; 2055 DT_SUBTABLE *ParentTable; 2056 DT_FIELD **PFieldList = (DT_FIELD **) List; 2057 DT_FIELD *SubtableStart; 2058 DT_FIELD *EntryStart; 2059 ACPI_HMAT_STRUCTURE *HmatStruct; 2060 ACPI_HMAT_LOCALITY *HmatLocality; 2061 ACPI_HMAT_CACHE *HmatCache; 2062 ACPI_DMTABLE_INFO *InfoTable; 2063 UINT32 IntPDNumber; 2064 UINT32 TgtPDNumber; 2065 UINT64 EntryNumber; 2066 UINT16 SMBIOSHandleNumber; 2067 2068 2069 ParentTable = DtPeekSubtable (); 2070 2071 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat, 2072 &Subtable); 2073 if (ACPI_FAILURE (Status)) 2074 { 2075 return (Status); 2076 } 2077 DtInsertSubtable (ParentTable, Subtable); 2078 2079 while (*PFieldList) 2080 { 2081 /* Compile HMAT structure header */ 2082 2083 SubtableStart = *PFieldList; 2084 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr, 2085 &Subtable); 2086 if (ACPI_FAILURE (Status)) 2087 { 2088 return (Status); 2089 } 2090 DtInsertSubtable (ParentTable, Subtable); 2091 2092 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer); 2093 HmatStruct->Length = Subtable->Length; 2094 2095 /* Compile HMAT structure body */ 2096 2097 switch (HmatStruct->Type) 2098 { 2099 case ACPI_HMAT_TYPE_ADDRESS_RANGE: 2100 2101 InfoTable = AcpiDmTableInfoHmat0; 2102 break; 2103 2104 case ACPI_HMAT_TYPE_LOCALITY: 2105 2106 InfoTable = AcpiDmTableInfoHmat1; 2107 break; 2108 2109 case ACPI_HMAT_TYPE_CACHE: 2110 2111 InfoTable = AcpiDmTableInfoHmat2; 2112 break; 2113 2114 default: 2115 2116 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT"); 2117 return (AE_ERROR); 2118 } 2119 2120 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 2121 if (ACPI_FAILURE (Status)) 2122 { 2123 return (Status); 2124 } 2125 DtInsertSubtable (ParentTable, Subtable); 2126 HmatStruct->Length += Subtable->Length; 2127 2128 /* Compile HMAT structure additional */ 2129 2130 switch (HmatStruct->Type) 2131 { 2132 case ACPI_HMAT_TYPE_LOCALITY: 2133 2134 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY, 2135 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 2136 2137 /* Compile initiator proximity domain list */ 2138 2139 IntPDNumber = 0; 2140 while (*PFieldList) 2141 { 2142 Status = DtCompileTable (PFieldList, 2143 AcpiDmTableInfoHmat1a, &Subtable); 2144 if (ACPI_FAILURE (Status)) 2145 { 2146 return (Status); 2147 } 2148 if (!Subtable) 2149 { 2150 break; 2151 } 2152 DtInsertSubtable (ParentTable, Subtable); 2153 HmatStruct->Length += Subtable->Length; 2154 IntPDNumber++; 2155 } 2156 HmatLocality->NumberOfInitiatorPDs = IntPDNumber; 2157 2158 /* Compile target proximity domain list */ 2159 2160 TgtPDNumber = 0; 2161 while (*PFieldList) 2162 { 2163 Status = DtCompileTable (PFieldList, 2164 AcpiDmTableInfoHmat1b, &Subtable); 2165 if (ACPI_FAILURE (Status)) 2166 { 2167 return (Status); 2168 } 2169 if (!Subtable) 2170 { 2171 break; 2172 } 2173 DtInsertSubtable (ParentTable, Subtable); 2174 HmatStruct->Length += Subtable->Length; 2175 TgtPDNumber++; 2176 } 2177 HmatLocality->NumberOfTargetPDs = TgtPDNumber; 2178 2179 /* Save start of the entries for reporting errors */ 2180 2181 EntryStart = *PFieldList; 2182 2183 /* Compile latency/bandwidth entries */ 2184 2185 EntryNumber = 0; 2186 while (*PFieldList) 2187 { 2188 Status = DtCompileTable (PFieldList, 2189 AcpiDmTableInfoHmat1c, &Subtable); 2190 if (ACPI_FAILURE (Status)) 2191 { 2192 return (Status); 2193 } 2194 if (!Subtable) 2195 { 2196 break; 2197 } 2198 DtInsertSubtable (ParentTable, Subtable); 2199 HmatStruct->Length += Subtable->Length; 2200 EntryNumber++; 2201 } 2202 2203 /* Validate number of entries */ 2204 2205 if (EntryNumber != 2206 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber)) 2207 { 2208 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT"); 2209 return (AE_ERROR); 2210 } 2211 break; 2212 2213 case ACPI_HMAT_TYPE_CACHE: 2214 2215 /* Compile SMBIOS handles */ 2216 2217 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE, 2218 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 2219 SMBIOSHandleNumber = 0; 2220 while (*PFieldList) 2221 { 2222 Status = DtCompileTable (PFieldList, 2223 AcpiDmTableInfoHmat2a, &Subtable); 2224 if (ACPI_FAILURE (Status)) 2225 { 2226 return (Status); 2227 } 2228 if (!Subtable) 2229 { 2230 break; 2231 } 2232 DtInsertSubtable (ParentTable, Subtable); 2233 HmatStruct->Length += Subtable->Length; 2234 SMBIOSHandleNumber++; 2235 } 2236 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber; 2237 break; 2238 2239 default: 2240 2241 break; 2242 } 2243 } 2244 2245 return (AE_OK); 2246 } 2247 2248 2249 /****************************************************************************** 2250 * 2251 * FUNCTION: DtCompileIort 2252 * 2253 * PARAMETERS: List - Current field list pointer 2254 * 2255 * RETURN: Status 2256 * 2257 * DESCRIPTION: Compile IORT. 2258 * 2259 *****************************************************************************/ 2260 2261 ACPI_STATUS 2262 DtCompileIort ( 2263 void **List) 2264 { 2265 ACPI_STATUS Status; 2266 DT_SUBTABLE *Subtable; 2267 DT_SUBTABLE *ParentTable; 2268 DT_FIELD **PFieldList = (DT_FIELD **) List; 2269 DT_FIELD *SubtableStart; 2270 ACPI_TABLE_HEADER *Table; 2271 ACPI_TABLE_IORT *Iort; 2272 ACPI_IORT_NODE *IortNode; 2273 ACPI_IORT_ITS_GROUP *IortItsGroup; 2274 ACPI_IORT_SMMU *IortSmmu; 2275 ACPI_IORT_RMR *IortRmr; 2276 UINT32 NodeNumber; 2277 UINT32 NodeLength; 2278 UINT32 IdMappingNumber; 2279 UINT32 ItsNumber; 2280 UINT32 ContextIrptNumber; 2281 UINT32 PmuIrptNumber; 2282 UINT32 PaddingLength; 2283 UINT8 Revision; 2284 UINT32 RmrCount; 2285 2286 2287 ParentTable = DtPeekSubtable (); 2288 2289 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort, 2290 &Subtable); 2291 if (ACPI_FAILURE (Status)) 2292 { 2293 return (Status); 2294 } 2295 DtInsertSubtable (ParentTable, Subtable); 2296 2297 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 2298 Revision = Table->Revision; 2299 2300 /* IORT Revisions E, E.a & E.c have known issues and are not supported */ 2301 2302 if (Revision == 1 || Revision == 2 || Revision == 4) 2303 { 2304 DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision"); 2305 return (AE_ERROR); 2306 } 2307 2308 /* 2309 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 2310 * should be taken to avoid accessing ACPI_TABLE_HEADER fields. 2311 */ 2312 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT, 2313 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 2314 2315 /* 2316 * OptionalPadding - Variable-length data 2317 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT)) 2318 * Optionally allows the generic data types to be used for filling 2319 * this field. 2320 */ 2321 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT); 2322 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad, 2323 &Subtable); 2324 if (ACPI_FAILURE (Status)) 2325 { 2326 return (Status); 2327 } 2328 if (Subtable) 2329 { 2330 DtInsertSubtable (ParentTable, Subtable); 2331 Iort->NodeOffset += Subtable->Length; 2332 } 2333 else 2334 { 2335 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList), 2336 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength); 2337 if (ACPI_FAILURE (Status)) 2338 { 2339 return (Status); 2340 } 2341 Iort->NodeOffset += PaddingLength; 2342 } 2343 2344 NodeNumber = 0; 2345 while (*PFieldList) 2346 { 2347 SubtableStart = *PFieldList; 2348 if (Revision == 0) 2349 { 2350 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr, 2351 &Subtable); 2352 } 2353 else if (Revision >= 3) 2354 { 2355 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3, 2356 &Subtable); 2357 } 2358 2359 if (ACPI_FAILURE (Status)) 2360 { 2361 return (Status); 2362 } 2363 2364 DtInsertSubtable (ParentTable, Subtable); 2365 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer); 2366 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData); 2367 2368 DtPushSubtable (Subtable); 2369 ParentTable = DtPeekSubtable (); 2370 2371 switch (IortNode->Type) 2372 { 2373 case ACPI_IORT_NODE_ITS_GROUP: 2374 2375 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0, 2376 &Subtable); 2377 if (ACPI_FAILURE (Status)) 2378 { 2379 return (Status); 2380 } 2381 2382 DtInsertSubtable (ParentTable, Subtable); 2383 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer); 2384 NodeLength += Subtable->Length; 2385 2386 ItsNumber = 0; 2387 while (*PFieldList) 2388 { 2389 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a, 2390 &Subtable); 2391 if (ACPI_FAILURE (Status)) 2392 { 2393 return (Status); 2394 } 2395 if (!Subtable) 2396 { 2397 break; 2398 } 2399 2400 DtInsertSubtable (ParentTable, Subtable); 2401 NodeLength += Subtable->Length; 2402 ItsNumber++; 2403 } 2404 2405 IortItsGroup->ItsCount = ItsNumber; 2406 break; 2407 2408 case ACPI_IORT_NODE_NAMED_COMPONENT: 2409 2410 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1, 2411 &Subtable); 2412 if (ACPI_FAILURE (Status)) 2413 { 2414 return (Status); 2415 } 2416 2417 DtInsertSubtable (ParentTable, Subtable); 2418 NodeLength += Subtable->Length; 2419 2420 /* 2421 * Padding - Variable-length data 2422 * Optionally allows the offset of the ID mappings to be used 2423 * for filling this field. 2424 */ 2425 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a, 2426 &Subtable); 2427 if (ACPI_FAILURE (Status)) 2428 { 2429 return (Status); 2430 } 2431 2432 if (Subtable) 2433 { 2434 DtInsertSubtable (ParentTable, Subtable); 2435 NodeLength += Subtable->Length; 2436 } 2437 else 2438 { 2439 if (NodeLength > IortNode->MappingOffset) 2440 { 2441 return (AE_BAD_DATA); 2442 } 2443 2444 if (NodeLength < IortNode->MappingOffset) 2445 { 2446 Status = DtCompilePadding ( 2447 IortNode->MappingOffset - NodeLength, 2448 &Subtable); 2449 if (ACPI_FAILURE (Status)) 2450 { 2451 return (Status); 2452 } 2453 2454 DtInsertSubtable (ParentTable, Subtable); 2455 NodeLength = IortNode->MappingOffset; 2456 } 2457 } 2458 break; 2459 2460 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX: 2461 2462 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2, 2463 &Subtable); 2464 if (ACPI_FAILURE (Status)) 2465 { 2466 return (Status); 2467 } 2468 2469 DtInsertSubtable (ParentTable, Subtable); 2470 NodeLength += Subtable->Length; 2471 break; 2472 2473 case ACPI_IORT_NODE_SMMU: 2474 2475 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3, 2476 &Subtable); 2477 if (ACPI_FAILURE (Status)) 2478 { 2479 return (Status); 2480 } 2481 2482 DtInsertSubtable (ParentTable, Subtable); 2483 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer); 2484 NodeLength += Subtable->Length; 2485 2486 /* Compile global interrupt array */ 2487 2488 IortSmmu->GlobalInterruptOffset = NodeLength; 2489 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a, 2490 &Subtable); 2491 if (ACPI_FAILURE (Status)) 2492 { 2493 return (Status); 2494 } 2495 2496 DtInsertSubtable (ParentTable, Subtable); 2497 NodeLength += Subtable->Length; 2498 2499 /* Compile context interrupt array */ 2500 2501 ContextIrptNumber = 0; 2502 IortSmmu->ContextInterruptOffset = NodeLength; 2503 while (*PFieldList) 2504 { 2505 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b, 2506 &Subtable); 2507 if (ACPI_FAILURE (Status)) 2508 { 2509 return (Status); 2510 } 2511 2512 if (!Subtable) 2513 { 2514 break; 2515 } 2516 2517 DtInsertSubtable (ParentTable, Subtable); 2518 NodeLength += Subtable->Length; 2519 ContextIrptNumber++; 2520 } 2521 2522 IortSmmu->ContextInterruptCount = ContextIrptNumber; 2523 2524 /* Compile PMU interrupt array */ 2525 2526 PmuIrptNumber = 0; 2527 IortSmmu->PmuInterruptOffset = NodeLength; 2528 while (*PFieldList) 2529 { 2530 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c, 2531 &Subtable); 2532 if (ACPI_FAILURE (Status)) 2533 { 2534 return (Status); 2535 } 2536 2537 if (!Subtable) 2538 { 2539 break; 2540 } 2541 2542 DtInsertSubtable (ParentTable, Subtable); 2543 NodeLength += Subtable->Length; 2544 PmuIrptNumber++; 2545 } 2546 2547 IortSmmu->PmuInterruptCount = PmuIrptNumber; 2548 break; 2549 2550 case ACPI_IORT_NODE_SMMU_V3: 2551 2552 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4, 2553 &Subtable); 2554 if (ACPI_FAILURE (Status)) 2555 { 2556 return (Status); 2557 } 2558 2559 DtInsertSubtable (ParentTable, Subtable); 2560 NodeLength += Subtable->Length; 2561 break; 2562 2563 case ACPI_IORT_NODE_PMCG: 2564 2565 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5, 2566 &Subtable); 2567 if (ACPI_FAILURE (Status)) 2568 { 2569 return (Status); 2570 } 2571 2572 DtInsertSubtable (ParentTable, Subtable); 2573 NodeLength += Subtable->Length; 2574 break; 2575 2576 case ACPI_IORT_NODE_RMR: 2577 2578 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6, 2579 &Subtable); 2580 if (ACPI_FAILURE (Status)) 2581 { 2582 return (Status); 2583 } 2584 2585 DtInsertSubtable (ParentTable, Subtable); 2586 IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer); 2587 NodeLength += Subtable->Length; 2588 2589 /* Compile RMR Descriptors */ 2590 2591 RmrCount = 0; 2592 IortRmr->RmrOffset = NodeLength; 2593 while (*PFieldList) 2594 { 2595 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a, 2596 &Subtable); 2597 if (ACPI_FAILURE (Status)) 2598 { 2599 return (Status); 2600 } 2601 2602 if (!Subtable) 2603 { 2604 break; 2605 } 2606 2607 DtInsertSubtable (ParentTable, Subtable); 2608 NodeLength += sizeof (ACPI_IORT_RMR_DESC); 2609 RmrCount++; 2610 } 2611 2612 IortRmr->RmrCount = RmrCount; 2613 break; 2614 2615 default: 2616 2617 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT"); 2618 return (AE_ERROR); 2619 } 2620 2621 /* Compile Array of ID mappings */ 2622 2623 IortNode->MappingOffset = NodeLength; 2624 IdMappingNumber = 0; 2625 while (*PFieldList) 2626 { 2627 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap, 2628 &Subtable); 2629 if (ACPI_FAILURE (Status)) 2630 { 2631 return (Status); 2632 } 2633 2634 if (!Subtable) 2635 { 2636 break; 2637 } 2638 2639 DtInsertSubtable (ParentTable, Subtable); 2640 NodeLength += sizeof (ACPI_IORT_ID_MAPPING); 2641 IdMappingNumber++; 2642 } 2643 2644 IortNode->MappingCount = IdMappingNumber; 2645 if (!IdMappingNumber) 2646 { 2647 IortNode->MappingOffset = 0; 2648 } 2649 2650 /* 2651 * Node length can be determined by DT_LENGTH option 2652 * IortNode->Length = NodeLength; 2653 */ 2654 DtPopSubtable (); 2655 ParentTable = DtPeekSubtable (); 2656 NodeNumber++; 2657 } 2658 2659 Iort->NodeCount = NodeNumber; 2660 return (AE_OK); 2661 } 2662 2663 2664 /****************************************************************************** 2665 * 2666 * FUNCTION: DtCompileIvrs 2667 * 2668 * PARAMETERS: List - Current field list pointer 2669 * 2670 * RETURN: Status 2671 * 2672 * DESCRIPTION: Compile IVRS. Notes: 2673 * The IVRS is essentially a flat table, with the following 2674 * structure: 2675 * <Main ACPI Table Header> 2676 * <Main subtable - virtualization info> 2677 * <IVHD> 2678 * <Device Entries> 2679 * ... 2680 * <IVHD> 2681 * <Device Entries> 2682 * <IVMD> 2683 * ... 2684 * 2685 *****************************************************************************/ 2686 2687 ACPI_STATUS 2688 DtCompileIvrs ( 2689 void **List) 2690 { 2691 ACPI_STATUS Status; 2692 DT_SUBTABLE *Subtable; 2693 DT_SUBTABLE *ParentTable; 2694 DT_SUBTABLE *MainSubtable; 2695 DT_FIELD **PFieldList = (DT_FIELD **) List; 2696 DT_FIELD *SubtableStart; 2697 ACPI_DMTABLE_INFO *InfoTable = NULL; 2698 UINT8 SubtableType; 2699 UINT8 Temp64[16]; 2700 UINT8 Temp8; 2701 2702 2703 /* Main table */ 2704 2705 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs, 2706 &Subtable); 2707 if (ACPI_FAILURE (Status)) 2708 { 2709 return (Status); 2710 } 2711 2712 ParentTable = DtPeekSubtable (); 2713 DtInsertSubtable (ParentTable, Subtable); 2714 DtPushSubtable (Subtable); 2715 2716 /* Save a pointer to the main subtable */ 2717 2718 MainSubtable = Subtable; 2719 2720 while (*PFieldList) 2721 { 2722 SubtableStart = *PFieldList; 2723 2724 /* Compile the SubtableType integer */ 2725 2726 DtCompileInteger (&SubtableType, *PFieldList, 1, 0); 2727 2728 switch (SubtableType) 2729 { 2730 2731 /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */ 2732 2733 case ACPI_IVRS_TYPE_HARDWARE1: 2734 2735 InfoTable = AcpiDmTableInfoIvrsHware1; 2736 break; 2737 2738 /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */ 2739 2740 case ACPI_IVRS_TYPE_HARDWARE2: 2741 case ACPI_IVRS_TYPE_HARDWARE3: 2742 2743 InfoTable = AcpiDmTableInfoIvrsHware23; 2744 break; 2745 2746 /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */ 2747 2748 case ACPI_IVRS_TYPE_MEMORY1: 2749 case ACPI_IVRS_TYPE_MEMORY2: 2750 case ACPI_IVRS_TYPE_MEMORY3: 2751 2752 InfoTable = AcpiDmTableInfoIvrsMemory; 2753 break; 2754 2755 /* 4-byte device entries */ 2756 2757 case ACPI_IVRS_TYPE_PAD4: 2758 case ACPI_IVRS_TYPE_ALL: 2759 case ACPI_IVRS_TYPE_SELECT: 2760 case ACPI_IVRS_TYPE_START: 2761 case ACPI_IVRS_TYPE_END: 2762 2763 InfoTable = AcpiDmTableInfoIvrs4; 2764 break; 2765 2766 /* 8-byte device entries, type A */ 2767 2768 case ACPI_IVRS_TYPE_ALIAS_SELECT: 2769 case ACPI_IVRS_TYPE_ALIAS_START: 2770 2771 InfoTable = AcpiDmTableInfoIvrs8a; 2772 break; 2773 2774 /* 8-byte device entries, type B */ 2775 2776 case ACPI_IVRS_TYPE_EXT_SELECT: 2777 case ACPI_IVRS_TYPE_EXT_START: 2778 2779 InfoTable = AcpiDmTableInfoIvrs8b; 2780 break; 2781 2782 /* 8-byte device entries, type C */ 2783 2784 case ACPI_IVRS_TYPE_SPECIAL: 2785 2786 InfoTable = AcpiDmTableInfoIvrs8c; 2787 break; 2788 2789 /* Variable device entries, type F0h */ 2790 2791 case ACPI_IVRS_TYPE_HID: 2792 2793 InfoTable = AcpiDmTableInfoIvrsHid; 2794 break; 2795 2796 default: 2797 2798 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, 2799 "IVRS Device Entry"); 2800 return (AE_ERROR); 2801 } 2802 2803 /* Compile the InfoTable from above */ 2804 2805 Status = DtCompileTable (PFieldList, InfoTable, 2806 &Subtable); 2807 if (ACPI_FAILURE (Status)) 2808 { 2809 return (Status); 2810 } 2811 2812 ParentTable = DtPeekSubtable (); 2813 if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 && 2814 SubtableType != ACPI_IVRS_TYPE_HARDWARE2 && 2815 SubtableType != ACPI_IVRS_TYPE_HARDWARE3 && 2816 SubtableType != ACPI_IVRS_TYPE_HID && 2817 SubtableType != ACPI_IVRS_TYPE_MEMORY1 && 2818 SubtableType != ACPI_IVRS_TYPE_MEMORY2 && 2819 SubtableType != ACPI_IVRS_TYPE_MEMORY3) 2820 { 2821 if (ParentTable) 2822 DtInsertSubtable (ParentTable, Subtable); 2823 } 2824 2825 switch (SubtableType) 2826 { 2827 case ACPI_IVRS_TYPE_HARDWARE1: 2828 case ACPI_IVRS_TYPE_HARDWARE2: 2829 case ACPI_IVRS_TYPE_HARDWARE3: 2830 case ACPI_IVRS_TYPE_MEMORY1: 2831 case ACPI_IVRS_TYPE_MEMORY2: 2832 case ACPI_IVRS_TYPE_MEMORY3: 2833 2834 /* Insert these IVHDs/IVMDs at the root subtable */ 2835 2836 DtInsertSubtable (MainSubtable, Subtable); 2837 DtPushSubtable (Subtable); 2838 break; 2839 2840 case ACPI_IVRS_TYPE_HID: 2841 2842 /* Special handling for the HID named device entry (0xF0) */ 2843 2844 if (ParentTable) 2845 { 2846 DtInsertSubtable (ParentTable, Subtable); 2847 } 2848 2849 /* 2850 * Process the HID value. First, get the HID value as a string. 2851 */ 2852 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); 2853 2854 /* 2855 * Determine if the HID is an integer or a string. 2856 * An integer is defined to be 32 bits, with the upper 32 bits 2857 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit 2858 * integer or a character string. If an integer, the lower 2859 * 4 bytes of the field contain the integer and the upper 2860 * 4 bytes are padded with 0". 2861 */ 2862 if (UtIsIdInteger ((UINT8 *) &Temp64)) 2863 { 2864 /* Compile the HID value as an integer */ 2865 2866 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); 2867 2868 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger, 2869 &Subtable); 2870 if (ACPI_FAILURE (Status)) 2871 { 2872 return (Status); 2873 } 2874 } 2875 else 2876 { 2877 /* Compile the HID value as a string */ 2878 2879 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString, 2880 &Subtable); 2881 if (ACPI_FAILURE (Status)) 2882 { 2883 return (Status); 2884 } 2885 } 2886 2887 DtInsertSubtable (ParentTable, Subtable); 2888 2889 /* 2890 * Process the CID value. First, get the CID value as a string. 2891 */ 2892 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); 2893 2894 if (UtIsIdInteger ((UINT8 *) &Temp64)) 2895 { 2896 /* Compile the CID value as an integer */ 2897 2898 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); 2899 2900 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger, 2901 &Subtable); 2902 if (ACPI_FAILURE (Status)) 2903 { 2904 return (Status); 2905 } 2906 } 2907 else 2908 { 2909 /* Compile the CID value as a string */ 2910 2911 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString, 2912 &Subtable); 2913 if (ACPI_FAILURE (Status)) 2914 { 2915 return (Status); 2916 } 2917 } 2918 2919 DtInsertSubtable (ParentTable, Subtable); 2920 2921 /* 2922 * Process the UID value. First, get and decode the "UID Format" field (Integer). 2923 */ 2924 if (!*PFieldList) 2925 { 2926 return (AE_OK); 2927 } 2928 2929 DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0); 2930 2931 switch (Temp8) 2932 { 2933 case ACPI_IVRS_UID_NOT_PRESENT: 2934 break; 2935 2936 case ACPI_IVRS_UID_IS_INTEGER: 2937 2938 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger, 2939 &Subtable); 2940 if (ACPI_FAILURE (Status)) 2941 { 2942 return (Status); 2943 } 2944 DtInsertSubtable (ParentTable, Subtable); 2945 break; 2946 2947 case ACPI_IVRS_UID_IS_STRING: 2948 2949 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString, 2950 &Subtable); 2951 if (ACPI_FAILURE (Status)) 2952 { 2953 return (Status); 2954 } 2955 DtInsertSubtable (ParentTable, Subtable); 2956 break; 2957 2958 default: 2959 2960 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart, 2961 "IVRS Device Entry"); 2962 return (AE_ERROR); 2963 } 2964 2965 default: 2966 2967 /* All other subtable types come through here */ 2968 break; 2969 } 2970 } 2971 2972 return (AE_OK); 2973 } 2974