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