1 /****************************************************************************** 2 * 3 * Module Name: dttable1.c - handling for specific ACPI tables 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2021, 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: DtCompileAsf 68 * 69 * PARAMETERS: List - Current field list pointer 70 * 71 * RETURN: Status 72 * 73 * DESCRIPTION: Compile ASF!. 74 * 75 *****************************************************************************/ 76 77 ACPI_STATUS 78 DtCompileAsf ( 79 void **List) 80 { 81 ACPI_ASF_INFO *AsfTable; 82 DT_SUBTABLE *Subtable; 83 DT_SUBTABLE *ParentTable; 84 ACPI_DMTABLE_INFO *InfoTable; 85 ACPI_DMTABLE_INFO *DataInfoTable = NULL; 86 UINT32 DataCount = 0; 87 ACPI_STATUS Status; 88 UINT32 i; 89 DT_FIELD **PFieldList = (DT_FIELD **) List; 90 DT_FIELD *SubtableStart; 91 92 93 while (*PFieldList) 94 { 95 SubtableStart = *PFieldList; 96 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr, 97 &Subtable); 98 if (ACPI_FAILURE (Status)) 99 { 100 return (Status); 101 } 102 103 ParentTable = DtPeekSubtable (); 104 DtInsertSubtable (ParentTable, Subtable); 105 DtPushSubtable (Subtable); 106 107 AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer); 108 109 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ 110 { 111 case ACPI_ASF_TYPE_INFO: 112 113 InfoTable = AcpiDmTableInfoAsf0; 114 break; 115 116 case ACPI_ASF_TYPE_ALERT: 117 118 InfoTable = AcpiDmTableInfoAsf1; 119 break; 120 121 case ACPI_ASF_TYPE_CONTROL: 122 123 InfoTable = AcpiDmTableInfoAsf2; 124 break; 125 126 case ACPI_ASF_TYPE_BOOT: 127 128 InfoTable = AcpiDmTableInfoAsf3; 129 break; 130 131 case ACPI_ASF_TYPE_ADDRESS: 132 133 InfoTable = AcpiDmTableInfoAsf4; 134 break; 135 136 default: 137 138 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); 139 return (AE_ERROR); 140 } 141 142 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 143 if (ACPI_FAILURE (Status)) 144 { 145 return (Status); 146 } 147 148 ParentTable = DtPeekSubtable (); 149 DtInsertSubtable (ParentTable, Subtable); 150 151 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ 152 { 153 case ACPI_ASF_TYPE_INFO: 154 155 DataInfoTable = NULL; 156 break; 157 158 case ACPI_ASF_TYPE_ALERT: 159 160 DataInfoTable = AcpiDmTableInfoAsf1a; 161 DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT, 162 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 163 sizeof (ACPI_ASF_HEADER)))->Alerts; 164 break; 165 166 case ACPI_ASF_TYPE_CONTROL: 167 168 DataInfoTable = AcpiDmTableInfoAsf2a; 169 DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE, 170 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 171 sizeof (ACPI_ASF_HEADER)))->Controls; 172 break; 173 174 case ACPI_ASF_TYPE_BOOT: 175 176 DataInfoTable = NULL; 177 break; 178 179 case ACPI_ASF_TYPE_ADDRESS: 180 181 DataInfoTable = TableInfoAsfAddress; 182 DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS, 183 ACPI_SUB_PTR (UINT8, Subtable->Buffer, 184 sizeof (ACPI_ASF_HEADER)))->Devices; 185 break; 186 187 default: 188 189 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); 190 return (AE_ERROR); 191 } 192 193 if (DataInfoTable) 194 { 195 switch (AsfTable->Header.Type & 0x7F) 196 { 197 case ACPI_ASF_TYPE_ADDRESS: 198 199 while (DataCount > 0) 200 { 201 Status = DtCompileTable (PFieldList, DataInfoTable, 202 &Subtable); 203 if (ACPI_FAILURE (Status)) 204 { 205 return (Status); 206 } 207 208 DtInsertSubtable (ParentTable, Subtable); 209 DataCount = DataCount - Subtable->Length; 210 } 211 break; 212 213 default: 214 215 for (i = 0; i < DataCount; i++) 216 { 217 Status = DtCompileTable (PFieldList, DataInfoTable, 218 &Subtable); 219 if (ACPI_FAILURE (Status)) 220 { 221 return (Status); 222 } 223 224 DtInsertSubtable (ParentTable, Subtable); 225 } 226 break; 227 } 228 } 229 230 DtPopSubtable (); 231 } 232 233 return (AE_OK); 234 } 235 236 237 /****************************************************************************** 238 * 239 * FUNCTION: DtCompileCedt 240 * 241 * PARAMETERS: List - Current field list pointer 242 * 243 * RETURN: Status 244 * 245 * DESCRIPTION: Compile CEDT. 246 * 247 *****************************************************************************/ 248 249 ACPI_STATUS 250 DtCompileCedt ( 251 void **List) 252 { 253 ACPI_STATUS Status; 254 DT_SUBTABLE *Subtable; 255 DT_SUBTABLE *ParentTable; 256 DT_FIELD **PFieldList = (DT_FIELD **) List; 257 ACPI_CEDT_HEADER *CedtHeader; 258 DT_FIELD *SubtableStart; 259 260 261 /* Walk the parse tree */ 262 263 while (*PFieldList) 264 { 265 SubtableStart = *PFieldList; 266 267 /* CEDT Header */ 268 269 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr, 270 &Subtable); 271 if (ACPI_FAILURE (Status)) 272 { 273 return (Status); 274 } 275 276 ParentTable = DtPeekSubtable (); 277 DtInsertSubtable (ParentTable, Subtable); 278 DtPushSubtable (Subtable); 279 280 CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer); 281 282 switch (CedtHeader->Type) 283 { 284 case ACPI_CEDT_TYPE_CHBS: 285 286 break; 287 288 default: 289 290 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT"); 291 return (AE_ERROR); 292 } 293 294 /* CEDT Subtable */ 295 296 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable); 297 if (ACPI_FAILURE (Status)) 298 { 299 return (Status); 300 } 301 302 ParentTable = DtPeekSubtable (); 303 DtInsertSubtable (ParentTable, Subtable); 304 DtPopSubtable (); 305 } 306 307 return (AE_OK); 308 } 309 310 311 /****************************************************************************** 312 * 313 * FUNCTION: DtCompileCpep 314 * 315 * PARAMETERS: List - Current field list pointer 316 * 317 * RETURN: Status 318 * 319 * DESCRIPTION: Compile CPEP. 320 * 321 *****************************************************************************/ 322 323 ACPI_STATUS 324 DtCompileCpep ( 325 void **List) 326 { 327 ACPI_STATUS Status; 328 329 330 Status = DtCompileTwoSubtables (List, 331 AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0); 332 return (Status); 333 } 334 335 336 /****************************************************************************** 337 * 338 * FUNCTION: DtCompileCsrt 339 * 340 * PARAMETERS: List - Current field list pointer 341 * 342 * RETURN: Status 343 * 344 * DESCRIPTION: Compile CSRT. 345 * 346 *****************************************************************************/ 347 348 ACPI_STATUS 349 DtCompileCsrt ( 350 void **List) 351 { 352 ACPI_STATUS Status = AE_OK; 353 DT_SUBTABLE *Subtable; 354 DT_SUBTABLE *ParentTable; 355 DT_FIELD **PFieldList = (DT_FIELD **) List; 356 UINT32 DescriptorCount; 357 UINT32 GroupLength; 358 359 360 /* Subtables (Resource Groups) */ 361 362 ParentTable = DtPeekSubtable (); 363 while (*PFieldList) 364 { 365 /* Resource group subtable */ 366 367 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0, 368 &Subtable); 369 if (ACPI_FAILURE (Status)) 370 { 371 return (Status); 372 } 373 374 /* Compute the number of resource descriptors */ 375 376 GroupLength = 377 (ACPI_CAST_PTR (ACPI_CSRT_GROUP, 378 Subtable->Buffer))->Length - 379 (ACPI_CAST_PTR (ACPI_CSRT_GROUP, 380 Subtable->Buffer))->SharedInfoLength - 381 sizeof (ACPI_CSRT_GROUP); 382 383 DescriptorCount = (GroupLength / 384 sizeof (ACPI_CSRT_DESCRIPTOR)); 385 386 DtInsertSubtable (ParentTable, Subtable); 387 DtPushSubtable (Subtable); 388 ParentTable = DtPeekSubtable (); 389 390 /* Shared info subtable (One per resource group) */ 391 392 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1, 393 &Subtable); 394 if (ACPI_FAILURE (Status)) 395 { 396 return (Status); 397 } 398 399 DtInsertSubtable (ParentTable, Subtable); 400 401 /* Sub-Subtables (Resource Descriptors) */ 402 403 while (*PFieldList && DescriptorCount) 404 { 405 406 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2, 407 &Subtable); 408 if (ACPI_FAILURE (Status)) 409 { 410 return (Status); 411 } 412 413 DtInsertSubtable (ParentTable, Subtable); 414 415 DtPushSubtable (Subtable); 416 ParentTable = DtPeekSubtable (); 417 if (*PFieldList) 418 { 419 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a, 420 &Subtable); 421 if (ACPI_FAILURE (Status)) 422 { 423 return (Status); 424 } 425 if (Subtable) 426 { 427 DtInsertSubtable (ParentTable, Subtable); 428 } 429 } 430 431 DtPopSubtable (); 432 ParentTable = DtPeekSubtable (); 433 DescriptorCount--; 434 } 435 436 DtPopSubtable (); 437 ParentTable = DtPeekSubtable (); 438 } 439 440 return (Status); 441 } 442 443 444 /****************************************************************************** 445 * 446 * FUNCTION: DtCompileDbg2 447 * 448 * PARAMETERS: List - Current field list pointer 449 * 450 * RETURN: Status 451 * 452 * DESCRIPTION: Compile DBG2. 453 * 454 *****************************************************************************/ 455 456 ACPI_STATUS 457 DtCompileDbg2 ( 458 void **List) 459 { 460 ACPI_STATUS Status; 461 DT_SUBTABLE *Subtable; 462 DT_SUBTABLE *ParentTable; 463 DT_FIELD **PFieldList = (DT_FIELD **) List; 464 UINT32 SubtableCount; 465 ACPI_DBG2_HEADER *Dbg2Header; 466 ACPI_DBG2_DEVICE *DeviceInfo; 467 UINT16 CurrentOffset; 468 UINT32 i; 469 470 471 /* Main table */ 472 473 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable); 474 if (ACPI_FAILURE (Status)) 475 { 476 return (Status); 477 } 478 479 ParentTable = DtPeekSubtable (); 480 DtInsertSubtable (ParentTable, Subtable); 481 482 /* Main table fields */ 483 484 Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer); 485 Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF ( 486 ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header); 487 488 SubtableCount = Dbg2Header->InfoCount; 489 DtPushSubtable (Subtable); 490 491 /* Process all Device Information subtables (Count = InfoCount) */ 492 493 while (*PFieldList && SubtableCount) 494 { 495 /* Subtable: Debug Device Information */ 496 497 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device, 498 &Subtable); 499 if (ACPI_FAILURE (Status)) 500 { 501 return (Status); 502 } 503 504 DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer); 505 CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE); 506 507 ParentTable = DtPeekSubtable (); 508 DtInsertSubtable (ParentTable, Subtable); 509 DtPushSubtable (Subtable); 510 511 ParentTable = DtPeekSubtable (); 512 513 /* BaseAddressRegister GAS array (Required, size is RegisterCount) */ 514 515 DeviceInfo->BaseAddressOffset = CurrentOffset; 516 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) 517 { 518 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr, 519 &Subtable); 520 if (ACPI_FAILURE (Status)) 521 { 522 return (Status); 523 } 524 525 CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS); 526 DtInsertSubtable (ParentTable, Subtable); 527 } 528 529 /* AddressSize array (Required, size = RegisterCount) */ 530 531 DeviceInfo->AddressSizeOffset = CurrentOffset; 532 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) 533 { 534 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size, 535 &Subtable); 536 if (ACPI_FAILURE (Status)) 537 { 538 return (Status); 539 } 540 541 CurrentOffset += (UINT16) sizeof (UINT32); 542 DtInsertSubtable (ParentTable, Subtable); 543 } 544 545 /* NamespaceString device identifier (Required, size = NamePathLength) */ 546 547 DeviceInfo->NamepathOffset = CurrentOffset; 548 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name, 549 &Subtable); 550 if (ACPI_FAILURE (Status)) 551 { 552 return (Status); 553 } 554 555 /* Update the device info header */ 556 557 DeviceInfo->NamepathLength = (UINT16) Subtable->Length; 558 CurrentOffset += (UINT16) DeviceInfo->NamepathLength; 559 DtInsertSubtable (ParentTable, Subtable); 560 561 /* OemData - Variable-length data (Optional, size = OemDataLength) */ 562 563 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData, 564 &Subtable); 565 if (Status == AE_END_OF_TABLE) 566 { 567 /* optional field was not found and we're at the end of the file */ 568 569 goto subtableDone; 570 } 571 else if (ACPI_FAILURE (Status)) 572 { 573 return (Status); 574 } 575 576 /* Update the device info header (zeros if no OEM data present) */ 577 578 DeviceInfo->OemDataOffset = 0; 579 DeviceInfo->OemDataLength = 0; 580 581 /* Optional subtable (OemData) */ 582 583 if (Subtable && Subtable->Length) 584 { 585 DeviceInfo->OemDataOffset = CurrentOffset; 586 DeviceInfo->OemDataLength = (UINT16) Subtable->Length; 587 588 DtInsertSubtable (ParentTable, Subtable); 589 } 590 subtableDone: 591 SubtableCount--; 592 DtPopSubtable (); /* Get next Device Information subtable */ 593 } 594 595 DtPopSubtable (); 596 return (AE_OK); 597 } 598 599 600 /****************************************************************************** 601 * 602 * FUNCTION: DtCompileDmar 603 * 604 * PARAMETERS: List - Current field list pointer 605 * 606 * RETURN: Status 607 * 608 * DESCRIPTION: Compile DMAR. 609 * 610 *****************************************************************************/ 611 612 ACPI_STATUS 613 DtCompileDmar ( 614 void **List) 615 { 616 ACPI_STATUS Status; 617 DT_SUBTABLE *Subtable; 618 DT_SUBTABLE *ParentTable; 619 DT_FIELD **PFieldList = (DT_FIELD **) List; 620 DT_FIELD *SubtableStart; 621 ACPI_DMTABLE_INFO *InfoTable; 622 ACPI_DMAR_HEADER *DmarHeader; 623 ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope; 624 UINT32 DeviceScopeLength; 625 UINT32 PciPathLength; 626 627 628 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable); 629 if (ACPI_FAILURE (Status)) 630 { 631 return (Status); 632 } 633 634 ParentTable = DtPeekSubtable (); 635 DtInsertSubtable (ParentTable, Subtable); 636 DtPushSubtable (Subtable); 637 638 while (*PFieldList) 639 { 640 /* DMAR Header */ 641 642 SubtableStart = *PFieldList; 643 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr, 644 &Subtable); 645 if (ACPI_FAILURE (Status)) 646 { 647 return (Status); 648 } 649 650 ParentTable = DtPeekSubtable (); 651 DtInsertSubtable (ParentTable, Subtable); 652 DtPushSubtable (Subtable); 653 654 DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer); 655 656 switch (DmarHeader->Type) 657 { 658 case ACPI_DMAR_TYPE_HARDWARE_UNIT: 659 660 InfoTable = AcpiDmTableInfoDmar0; 661 break; 662 663 case ACPI_DMAR_TYPE_RESERVED_MEMORY: 664 665 InfoTable = AcpiDmTableInfoDmar1; 666 break; 667 668 case ACPI_DMAR_TYPE_ROOT_ATS: 669 670 InfoTable = AcpiDmTableInfoDmar2; 671 break; 672 673 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY: 674 675 InfoTable = AcpiDmTableInfoDmar3; 676 break; 677 678 case ACPI_DMAR_TYPE_NAMESPACE: 679 680 InfoTable = AcpiDmTableInfoDmar4; 681 break; 682 683 default: 684 685 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR"); 686 return (AE_ERROR); 687 } 688 689 /* DMAR Subtable */ 690 691 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 692 if (ACPI_FAILURE (Status)) 693 { 694 return (Status); 695 } 696 697 ParentTable = DtPeekSubtable (); 698 DtInsertSubtable (ParentTable, Subtable); 699 700 /* 701 * Optional Device Scope subtables 702 */ 703 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) || 704 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE)) 705 { 706 /* These types do not support device scopes */ 707 708 DtPopSubtable (); 709 continue; 710 } 711 712 DtPushSubtable (Subtable); 713 DeviceScopeLength = DmarHeader->Length - Subtable->Length - 714 ParentTable->Length; 715 while (DeviceScopeLength) 716 { 717 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope, 718 &Subtable); 719 if (Status == AE_NOT_FOUND) 720 { 721 break; 722 } 723 724 ParentTable = DtPeekSubtable (); 725 DtInsertSubtable (ParentTable, Subtable); 726 DtPushSubtable (Subtable); 727 728 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer); 729 730 /* Optional PCI Paths */ 731 732 PciPathLength = DmarDeviceScope->Length - Subtable->Length; 733 while (PciPathLength) 734 { 735 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath, 736 &Subtable); 737 if (Status == AE_NOT_FOUND) 738 { 739 DtPopSubtable (); 740 break; 741 } 742 743 ParentTable = DtPeekSubtable (); 744 DtInsertSubtable (ParentTable, Subtable); 745 PciPathLength -= Subtable->Length; 746 } 747 748 DtPopSubtable (); 749 DeviceScopeLength -= DmarDeviceScope->Length; 750 } 751 752 DtPopSubtable (); 753 DtPopSubtable (); 754 } 755 756 return (AE_OK); 757 } 758 759 760 /****************************************************************************** 761 * 762 * FUNCTION: DtCompileDrtm 763 * 764 * PARAMETERS: List - Current field list pointer 765 * 766 * RETURN: Status 767 * 768 * DESCRIPTION: Compile DRTM. 769 * 770 *****************************************************************************/ 771 772 ACPI_STATUS 773 DtCompileDrtm ( 774 void **List) 775 { 776 ACPI_STATUS Status; 777 DT_SUBTABLE *Subtable; 778 DT_SUBTABLE *ParentTable; 779 DT_FIELD **PFieldList = (DT_FIELD **) List; 780 UINT32 Count; 781 /* ACPI_TABLE_DRTM *Drtm; */ 782 ACPI_DRTM_VTABLE_LIST *DrtmVtl; 783 ACPI_DRTM_RESOURCE_LIST *DrtmRl; 784 /* ACPI_DRTM_DPS_ID *DrtmDps; */ 785 786 787 ParentTable = DtPeekSubtable (); 788 789 /* Compile DRTM header */ 790 791 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm, 792 &Subtable); 793 if (ACPI_FAILURE (Status)) 794 { 795 return (Status); 796 } 797 DtInsertSubtable (ParentTable, Subtable); 798 799 /* 800 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 801 * should be taken to avoid accessing ACPI_TABLE_HADER fields. 802 */ 803 #if 0 804 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM, 805 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 806 #endif 807 /* Compile VTL */ 808 809 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0, 810 &Subtable); 811 if (ACPI_FAILURE (Status)) 812 { 813 return (Status); 814 } 815 816 DtInsertSubtable (ParentTable, Subtable); 817 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer); 818 819 DtPushSubtable (Subtable); 820 ParentTable = DtPeekSubtable (); 821 Count = 0; 822 823 while (*PFieldList) 824 { 825 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a, 826 &Subtable); 827 if (ACPI_FAILURE (Status)) 828 { 829 return (Status); 830 } 831 if (!Subtable) 832 { 833 break; 834 } 835 DtInsertSubtable (ParentTable, Subtable); 836 Count++; 837 } 838 839 DrtmVtl->ValidatedTableCount = Count; 840 DtPopSubtable (); 841 ParentTable = DtPeekSubtable (); 842 843 /* Compile RL */ 844 845 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1, 846 &Subtable); 847 if (ACPI_FAILURE (Status)) 848 { 849 return (Status); 850 } 851 852 DtInsertSubtable (ParentTable, Subtable); 853 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer); 854 855 DtPushSubtable (Subtable); 856 ParentTable = DtPeekSubtable (); 857 Count = 0; 858 859 while (*PFieldList) 860 { 861 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a, 862 &Subtable); 863 if (ACPI_FAILURE (Status)) 864 { 865 return (Status); 866 } 867 868 if (!Subtable) 869 { 870 break; 871 } 872 873 DtInsertSubtable (ParentTable, Subtable); 874 Count++; 875 } 876 877 DrtmRl->ResourceCount = Count; 878 DtPopSubtable (); 879 ParentTable = DtPeekSubtable (); 880 881 /* Compile DPS */ 882 883 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2, 884 &Subtable); 885 if (ACPI_FAILURE (Status)) 886 { 887 return (Status); 888 } 889 DtInsertSubtable (ParentTable, Subtable); 890 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/ 891 892 893 return (AE_OK); 894 } 895 896 897 /****************************************************************************** 898 * 899 * FUNCTION: DtCompileEinj 900 * 901 * PARAMETERS: List - Current field list pointer 902 * 903 * RETURN: Status 904 * 905 * DESCRIPTION: Compile EINJ. 906 * 907 *****************************************************************************/ 908 909 ACPI_STATUS 910 DtCompileEinj ( 911 void **List) 912 { 913 ACPI_STATUS Status; 914 915 916 Status = DtCompileTwoSubtables (List, 917 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0); 918 return (Status); 919 } 920 921 922 /****************************************************************************** 923 * 924 * FUNCTION: DtCompileErst 925 * 926 * PARAMETERS: List - Current field list pointer 927 * 928 * RETURN: Status 929 * 930 * DESCRIPTION: Compile ERST. 931 * 932 *****************************************************************************/ 933 934 ACPI_STATUS 935 DtCompileErst ( 936 void **List) 937 { 938 ACPI_STATUS Status; 939 940 941 Status = DtCompileTwoSubtables (List, 942 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0); 943 return (Status); 944 } 945 946 947 /****************************************************************************** 948 * 949 * FUNCTION: DtCompileGtdt 950 * 951 * PARAMETERS: List - Current field list pointer 952 * 953 * RETURN: Status 954 * 955 * DESCRIPTION: Compile GTDT. 956 * 957 *****************************************************************************/ 958 959 ACPI_STATUS 960 DtCompileGtdt ( 961 void **List) 962 { 963 ACPI_STATUS Status; 964 DT_SUBTABLE *Subtable; 965 DT_SUBTABLE *ParentTable; 966 DT_FIELD **PFieldList = (DT_FIELD **) List; 967 DT_FIELD *SubtableStart; 968 ACPI_SUBTABLE_HEADER *GtdtHeader; 969 ACPI_DMTABLE_INFO *InfoTable; 970 UINT32 GtCount; 971 ACPI_TABLE_HEADER *Header; 972 973 974 ParentTable = DtPeekSubtable (); 975 976 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 977 978 /* Compile the main table */ 979 980 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt, 981 &Subtable); 982 if (ACPI_FAILURE (Status)) 983 { 984 return (Status); 985 } 986 987 /* GTDT revision 3 later contains 2 extra fields before subtables */ 988 989 if (Header->Revision > 2) 990 { 991 ParentTable = DtPeekSubtable (); 992 DtInsertSubtable (ParentTable, Subtable); 993 994 Status = DtCompileTable (PFieldList, 995 AcpiDmTableInfoGtdtEl2, &Subtable); 996 if (ACPI_FAILURE (Status)) 997 { 998 return (Status); 999 } 1000 } 1001 1002 ParentTable = DtPeekSubtable (); 1003 DtInsertSubtable (ParentTable, Subtable); 1004 1005 while (*PFieldList) 1006 { 1007 SubtableStart = *PFieldList; 1008 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr, 1009 &Subtable); 1010 if (ACPI_FAILURE (Status)) 1011 { 1012 return (Status); 1013 } 1014 1015 ParentTable = DtPeekSubtable (); 1016 DtInsertSubtable (ParentTable, Subtable); 1017 DtPushSubtable (Subtable); 1018 1019 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer); 1020 1021 switch (GtdtHeader->Type) 1022 { 1023 case ACPI_GTDT_TYPE_TIMER_BLOCK: 1024 1025 InfoTable = AcpiDmTableInfoGtdt0; 1026 break; 1027 1028 case ACPI_GTDT_TYPE_WATCHDOG: 1029 1030 InfoTable = AcpiDmTableInfoGtdt1; 1031 break; 1032 1033 default: 1034 1035 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT"); 1036 return (AE_ERROR); 1037 } 1038 1039 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1040 if (ACPI_FAILURE (Status)) 1041 { 1042 return (Status); 1043 } 1044 1045 ParentTable = DtPeekSubtable (); 1046 DtInsertSubtable (ParentTable, Subtable); 1047 1048 /* 1049 * Additional GT block subtable data 1050 */ 1051 1052 switch (GtdtHeader->Type) 1053 { 1054 case ACPI_GTDT_TYPE_TIMER_BLOCK: 1055 1056 DtPushSubtable (Subtable); 1057 ParentTable = DtPeekSubtable (); 1058 1059 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK, 1060 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount; 1061 1062 while (GtCount) 1063 { 1064 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a, 1065 &Subtable); 1066 if (ACPI_FAILURE (Status)) 1067 { 1068 return (Status); 1069 } 1070 1071 DtInsertSubtable (ParentTable, Subtable); 1072 GtCount--; 1073 } 1074 1075 DtPopSubtable (); 1076 break; 1077 1078 default: 1079 1080 break; 1081 } 1082 1083 DtPopSubtable (); 1084 } 1085 1086 return (AE_OK); 1087 } 1088 1089 1090 /****************************************************************************** 1091 * 1092 * FUNCTION: DtCompileFpdt 1093 * 1094 * PARAMETERS: List - Current field list pointer 1095 * 1096 * RETURN: Status 1097 * 1098 * DESCRIPTION: Compile FPDT. 1099 * 1100 *****************************************************************************/ 1101 1102 ACPI_STATUS 1103 DtCompileFpdt ( 1104 void **List) 1105 { 1106 ACPI_STATUS Status; 1107 ACPI_FPDT_HEADER *FpdtHeader; 1108 DT_SUBTABLE *Subtable; 1109 DT_SUBTABLE *ParentTable; 1110 ACPI_DMTABLE_INFO *InfoTable; 1111 DT_FIELD **PFieldList = (DT_FIELD **) List; 1112 DT_FIELD *SubtableStart; 1113 1114 1115 while (*PFieldList) 1116 { 1117 SubtableStart = *PFieldList; 1118 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr, 1119 &Subtable); 1120 if (ACPI_FAILURE (Status)) 1121 { 1122 return (Status); 1123 } 1124 1125 ParentTable = DtPeekSubtable (); 1126 DtInsertSubtable (ParentTable, Subtable); 1127 DtPushSubtable (Subtable); 1128 1129 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer); 1130 1131 switch (FpdtHeader->Type) 1132 { 1133 case ACPI_FPDT_TYPE_BOOT: 1134 1135 InfoTable = AcpiDmTableInfoFpdt0; 1136 break; 1137 1138 case ACPI_FPDT_TYPE_S3PERF: 1139 1140 InfoTable = AcpiDmTableInfoFpdt1; 1141 break; 1142 1143 default: 1144 1145 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT"); 1146 return (AE_ERROR); 1147 break; 1148 } 1149 1150 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1151 if (ACPI_FAILURE (Status)) 1152 { 1153 return (Status); 1154 } 1155 1156 ParentTable = DtPeekSubtable (); 1157 DtInsertSubtable (ParentTable, Subtable); 1158 DtPopSubtable (); 1159 } 1160 1161 return (AE_OK); 1162 } 1163 1164 1165 /****************************************************************************** 1166 * 1167 * FUNCTION: DtCompileHest 1168 * 1169 * PARAMETERS: List - Current field list pointer 1170 * 1171 * RETURN: Status 1172 * 1173 * DESCRIPTION: Compile HEST. 1174 * 1175 *****************************************************************************/ 1176 1177 ACPI_STATUS 1178 DtCompileHest ( 1179 void **List) 1180 { 1181 ACPI_STATUS Status; 1182 DT_SUBTABLE *Subtable; 1183 DT_SUBTABLE *ParentTable; 1184 DT_FIELD **PFieldList = (DT_FIELD **) List; 1185 DT_FIELD *SubtableStart; 1186 ACPI_DMTABLE_INFO *InfoTable; 1187 UINT16 Type; 1188 UINT32 BankCount; 1189 1190 1191 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest, 1192 &Subtable); 1193 if (ACPI_FAILURE (Status)) 1194 { 1195 return (Status); 1196 } 1197 1198 ParentTable = DtPeekSubtable (); 1199 DtInsertSubtable (ParentTable, Subtable); 1200 1201 while (*PFieldList) 1202 { 1203 /* Get subtable type */ 1204 1205 SubtableStart = *PFieldList; 1206 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0); 1207 1208 switch (Type) 1209 { 1210 case ACPI_HEST_TYPE_IA32_CHECK: 1211 1212 InfoTable = AcpiDmTableInfoHest0; 1213 break; 1214 1215 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 1216 1217 InfoTable = AcpiDmTableInfoHest1; 1218 break; 1219 1220 case ACPI_HEST_TYPE_IA32_NMI: 1221 1222 InfoTable = AcpiDmTableInfoHest2; 1223 break; 1224 1225 case ACPI_HEST_TYPE_AER_ROOT_PORT: 1226 1227 InfoTable = AcpiDmTableInfoHest6; 1228 break; 1229 1230 case ACPI_HEST_TYPE_AER_ENDPOINT: 1231 1232 InfoTable = AcpiDmTableInfoHest7; 1233 break; 1234 1235 case ACPI_HEST_TYPE_AER_BRIDGE: 1236 1237 InfoTable = AcpiDmTableInfoHest8; 1238 break; 1239 1240 case ACPI_HEST_TYPE_GENERIC_ERROR: 1241 1242 InfoTable = AcpiDmTableInfoHest9; 1243 break; 1244 1245 case ACPI_HEST_TYPE_GENERIC_ERROR_V2: 1246 1247 InfoTable = AcpiDmTableInfoHest10; 1248 break; 1249 1250 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 1251 1252 InfoTable = AcpiDmTableInfoHest11; 1253 break; 1254 1255 default: 1256 1257 /* Cannot continue on unknown type */ 1258 1259 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST"); 1260 return (AE_ERROR); 1261 } 1262 1263 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1264 if (ACPI_FAILURE (Status)) 1265 { 1266 return (Status); 1267 } 1268 1269 DtInsertSubtable (ParentTable, Subtable); 1270 1271 /* 1272 * Additional subtable data - IA32 Error Bank(s) 1273 */ 1274 BankCount = 0; 1275 switch (Type) 1276 { 1277 case ACPI_HEST_TYPE_IA32_CHECK: 1278 1279 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK, 1280 Subtable->Buffer))->NumHardwareBanks; 1281 break; 1282 1283 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: 1284 1285 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED, 1286 Subtable->Buffer))->NumHardwareBanks; 1287 break; 1288 1289 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: 1290 1291 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK, 1292 Subtable->Buffer))->NumHardwareBanks; 1293 break; 1294 1295 default: 1296 1297 break; 1298 } 1299 1300 while (BankCount) 1301 { 1302 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank, 1303 &Subtable); 1304 if (ACPI_FAILURE (Status)) 1305 { 1306 return (Status); 1307 } 1308 1309 DtInsertSubtable (ParentTable, Subtable); 1310 BankCount--; 1311 } 1312 } 1313 1314 return (AE_OK); 1315 } 1316 1317 1318 /****************************************************************************** 1319 * 1320 * FUNCTION: DtCompileHmat 1321 * 1322 * PARAMETERS: List - Current field list pointer 1323 * 1324 * RETURN: Status 1325 * 1326 * DESCRIPTION: Compile HMAT. 1327 * 1328 *****************************************************************************/ 1329 1330 ACPI_STATUS 1331 DtCompileHmat ( 1332 void **List) 1333 { 1334 ACPI_STATUS Status; 1335 DT_SUBTABLE *Subtable; 1336 DT_SUBTABLE *ParentTable; 1337 DT_FIELD **PFieldList = (DT_FIELD **) List; 1338 DT_FIELD *SubtableStart; 1339 DT_FIELD *EntryStart; 1340 ACPI_HMAT_STRUCTURE *HmatStruct; 1341 ACPI_HMAT_LOCALITY *HmatLocality; 1342 ACPI_HMAT_CACHE *HmatCache; 1343 ACPI_DMTABLE_INFO *InfoTable; 1344 UINT32 IntPDNumber; 1345 UINT32 TgtPDNumber; 1346 UINT64 EntryNumber; 1347 UINT16 SMBIOSHandleNumber; 1348 1349 1350 ParentTable = DtPeekSubtable (); 1351 1352 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat, 1353 &Subtable); 1354 if (ACPI_FAILURE (Status)) 1355 { 1356 return (Status); 1357 } 1358 DtInsertSubtable (ParentTable, Subtable); 1359 1360 while (*PFieldList) 1361 { 1362 /* Compile HMAT structure header */ 1363 1364 SubtableStart = *PFieldList; 1365 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr, 1366 &Subtable); 1367 if (ACPI_FAILURE (Status)) 1368 { 1369 return (Status); 1370 } 1371 DtInsertSubtable (ParentTable, Subtable); 1372 1373 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer); 1374 HmatStruct->Length = Subtable->Length; 1375 1376 /* Compile HMAT structure body */ 1377 1378 switch (HmatStruct->Type) 1379 { 1380 case ACPI_HMAT_TYPE_ADDRESS_RANGE: 1381 1382 InfoTable = AcpiDmTableInfoHmat0; 1383 break; 1384 1385 case ACPI_HMAT_TYPE_LOCALITY: 1386 1387 InfoTable = AcpiDmTableInfoHmat1; 1388 break; 1389 1390 case ACPI_HMAT_TYPE_CACHE: 1391 1392 InfoTable = AcpiDmTableInfoHmat2; 1393 break; 1394 1395 default: 1396 1397 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT"); 1398 return (AE_ERROR); 1399 } 1400 1401 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 1402 if (ACPI_FAILURE (Status)) 1403 { 1404 return (Status); 1405 } 1406 DtInsertSubtable (ParentTable, Subtable); 1407 HmatStruct->Length += Subtable->Length; 1408 1409 /* Compile HMAT structure additionals */ 1410 1411 switch (HmatStruct->Type) 1412 { 1413 case ACPI_HMAT_TYPE_LOCALITY: 1414 1415 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY, 1416 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 1417 1418 /* Compile initiator proximity domain list */ 1419 1420 IntPDNumber = 0; 1421 while (*PFieldList) 1422 { 1423 Status = DtCompileTable (PFieldList, 1424 AcpiDmTableInfoHmat1a, &Subtable); 1425 if (ACPI_FAILURE (Status)) 1426 { 1427 return (Status); 1428 } 1429 if (!Subtable) 1430 { 1431 break; 1432 } 1433 DtInsertSubtable (ParentTable, Subtable); 1434 HmatStruct->Length += Subtable->Length; 1435 IntPDNumber++; 1436 } 1437 HmatLocality->NumberOfInitiatorPDs = IntPDNumber; 1438 1439 /* Compile target proximity domain list */ 1440 1441 TgtPDNumber = 0; 1442 while (*PFieldList) 1443 { 1444 Status = DtCompileTable (PFieldList, 1445 AcpiDmTableInfoHmat1b, &Subtable); 1446 if (ACPI_FAILURE (Status)) 1447 { 1448 return (Status); 1449 } 1450 if (!Subtable) 1451 { 1452 break; 1453 } 1454 DtInsertSubtable (ParentTable, Subtable); 1455 HmatStruct->Length += Subtable->Length; 1456 TgtPDNumber++; 1457 } 1458 HmatLocality->NumberOfTargetPDs = TgtPDNumber; 1459 1460 /* Save start of the entries for reporting errors */ 1461 1462 EntryStart = *PFieldList; 1463 1464 /* Compile latency/bandwidth entries */ 1465 1466 EntryNumber = 0; 1467 while (*PFieldList) 1468 { 1469 Status = DtCompileTable (PFieldList, 1470 AcpiDmTableInfoHmat1c, &Subtable); 1471 if (ACPI_FAILURE (Status)) 1472 { 1473 return (Status); 1474 } 1475 if (!Subtable) 1476 { 1477 break; 1478 } 1479 DtInsertSubtable (ParentTable, Subtable); 1480 HmatStruct->Length += Subtable->Length; 1481 EntryNumber++; 1482 } 1483 1484 /* Validate number of entries */ 1485 1486 if (EntryNumber != 1487 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber)) 1488 { 1489 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT"); 1490 return (AE_ERROR); 1491 } 1492 break; 1493 1494 case ACPI_HMAT_TYPE_CACHE: 1495 1496 /* Compile SMBIOS handles */ 1497 1498 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE, 1499 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); 1500 SMBIOSHandleNumber = 0; 1501 while (*PFieldList) 1502 { 1503 Status = DtCompileTable (PFieldList, 1504 AcpiDmTableInfoHmat2a, &Subtable); 1505 if (ACPI_FAILURE (Status)) 1506 { 1507 return (Status); 1508 } 1509 if (!Subtable) 1510 { 1511 break; 1512 } 1513 DtInsertSubtable (ParentTable, Subtable); 1514 HmatStruct->Length += Subtable->Length; 1515 SMBIOSHandleNumber++; 1516 } 1517 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber; 1518 break; 1519 1520 default: 1521 1522 break; 1523 } 1524 } 1525 1526 return (AE_OK); 1527 } 1528 1529 1530 /****************************************************************************** 1531 * 1532 * FUNCTION: DtCompileIort 1533 * 1534 * PARAMETERS: List - Current field list pointer 1535 * 1536 * RETURN: Status 1537 * 1538 * DESCRIPTION: Compile IORT. 1539 * 1540 *****************************************************************************/ 1541 1542 ACPI_STATUS 1543 DtCompileIort ( 1544 void **List) 1545 { 1546 ACPI_STATUS Status; 1547 DT_SUBTABLE *Subtable; 1548 DT_SUBTABLE *ParentTable; 1549 DT_FIELD **PFieldList = (DT_FIELD **) List; 1550 DT_FIELD *SubtableStart; 1551 ACPI_TABLE_HEADER *Table; 1552 ACPI_TABLE_IORT *Iort; 1553 ACPI_IORT_NODE *IortNode; 1554 ACPI_IORT_ITS_GROUP *IortItsGroup; 1555 ACPI_IORT_SMMU *IortSmmu; 1556 ACPI_IORT_RMR *IortRmr; 1557 UINT32 NodeNumber; 1558 UINT32 NodeLength; 1559 UINT32 IdMappingNumber; 1560 UINT32 ItsNumber; 1561 UINT32 ContextIrptNumber; 1562 UINT32 PmuIrptNumber; 1563 UINT32 PaddingLength; 1564 UINT8 Revision; 1565 UINT32 RmrCount; 1566 1567 1568 ParentTable = DtPeekSubtable (); 1569 1570 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort, 1571 &Subtable); 1572 if (ACPI_FAILURE (Status)) 1573 { 1574 return (Status); 1575 } 1576 DtInsertSubtable (ParentTable, Subtable); 1577 1578 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); 1579 Revision = Table->Revision; 1580 1581 /* Both IORT Rev E and E.a have known issues and are not supported */ 1582 1583 if (Revision == 1 || Revision == 2) 1584 { 1585 DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision"); 1586 return (AE_ERROR); 1587 } 1588 1589 /* 1590 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care 1591 * should be taken to avoid accessing ACPI_TABLE_HEADER fields. 1592 */ 1593 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT, 1594 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); 1595 1596 /* 1597 * OptionalPadding - Variable-length data 1598 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT)) 1599 * Optionally allows the generic data types to be used for filling 1600 * this field. 1601 */ 1602 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT); 1603 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad, 1604 &Subtable); 1605 if (ACPI_FAILURE (Status)) 1606 { 1607 return (Status); 1608 } 1609 if (Subtable) 1610 { 1611 DtInsertSubtable (ParentTable, Subtable); 1612 Iort->NodeOffset += Subtable->Length; 1613 } 1614 else 1615 { 1616 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList), 1617 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength); 1618 if (ACPI_FAILURE (Status)) 1619 { 1620 return (Status); 1621 } 1622 Iort->NodeOffset += PaddingLength; 1623 } 1624 1625 NodeNumber = 0; 1626 while (*PFieldList) 1627 { 1628 SubtableStart = *PFieldList; 1629 if (Revision == 0) 1630 { 1631 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr, 1632 &Subtable); 1633 } 1634 else if (Revision >= 3) 1635 { 1636 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3, 1637 &Subtable); 1638 } 1639 1640 if (ACPI_FAILURE (Status)) 1641 { 1642 return (Status); 1643 } 1644 1645 DtInsertSubtable (ParentTable, Subtable); 1646 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer); 1647 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData); 1648 1649 DtPushSubtable (Subtable); 1650 ParentTable = DtPeekSubtable (); 1651 1652 switch (IortNode->Type) 1653 { 1654 case ACPI_IORT_NODE_ITS_GROUP: 1655 1656 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0, 1657 &Subtable); 1658 if (ACPI_FAILURE (Status)) 1659 { 1660 return (Status); 1661 } 1662 1663 DtInsertSubtable (ParentTable, Subtable); 1664 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer); 1665 NodeLength += Subtable->Length; 1666 1667 ItsNumber = 0; 1668 while (*PFieldList) 1669 { 1670 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a, 1671 &Subtable); 1672 if (ACPI_FAILURE (Status)) 1673 { 1674 return (Status); 1675 } 1676 if (!Subtable) 1677 { 1678 break; 1679 } 1680 1681 DtInsertSubtable (ParentTable, Subtable); 1682 NodeLength += Subtable->Length; 1683 ItsNumber++; 1684 } 1685 1686 IortItsGroup->ItsCount = ItsNumber; 1687 break; 1688 1689 case ACPI_IORT_NODE_NAMED_COMPONENT: 1690 1691 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1, 1692 &Subtable); 1693 if (ACPI_FAILURE (Status)) 1694 { 1695 return (Status); 1696 } 1697 1698 DtInsertSubtable (ParentTable, Subtable); 1699 NodeLength += Subtable->Length; 1700 1701 /* 1702 * Padding - Variable-length data 1703 * Optionally allows the offset of the ID mappings to be used 1704 * for filling this field. 1705 */ 1706 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a, 1707 &Subtable); 1708 if (ACPI_FAILURE (Status)) 1709 { 1710 return (Status); 1711 } 1712 1713 if (Subtable) 1714 { 1715 DtInsertSubtable (ParentTable, Subtable); 1716 NodeLength += Subtable->Length; 1717 } 1718 else 1719 { 1720 if (NodeLength > IortNode->MappingOffset) 1721 { 1722 return (AE_BAD_DATA); 1723 } 1724 1725 if (NodeLength < IortNode->MappingOffset) 1726 { 1727 Status = DtCompilePadding ( 1728 IortNode->MappingOffset - NodeLength, 1729 &Subtable); 1730 if (ACPI_FAILURE (Status)) 1731 { 1732 return (Status); 1733 } 1734 1735 DtInsertSubtable (ParentTable, Subtable); 1736 NodeLength = IortNode->MappingOffset; 1737 } 1738 } 1739 break; 1740 1741 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX: 1742 1743 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2, 1744 &Subtable); 1745 if (ACPI_FAILURE (Status)) 1746 { 1747 return (Status); 1748 } 1749 1750 DtInsertSubtable (ParentTable, Subtable); 1751 NodeLength += Subtable->Length; 1752 break; 1753 1754 case ACPI_IORT_NODE_SMMU: 1755 1756 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3, 1757 &Subtable); 1758 if (ACPI_FAILURE (Status)) 1759 { 1760 return (Status); 1761 } 1762 1763 DtInsertSubtable (ParentTable, Subtable); 1764 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer); 1765 NodeLength += Subtable->Length; 1766 1767 /* Compile global interrupt array */ 1768 1769 IortSmmu->GlobalInterruptOffset = NodeLength; 1770 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a, 1771 &Subtable); 1772 if (ACPI_FAILURE (Status)) 1773 { 1774 return (Status); 1775 } 1776 1777 DtInsertSubtable (ParentTable, Subtable); 1778 NodeLength += Subtable->Length; 1779 1780 /* Compile context interrupt array */ 1781 1782 ContextIrptNumber = 0; 1783 IortSmmu->ContextInterruptOffset = NodeLength; 1784 while (*PFieldList) 1785 { 1786 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b, 1787 &Subtable); 1788 if (ACPI_FAILURE (Status)) 1789 { 1790 return (Status); 1791 } 1792 1793 if (!Subtable) 1794 { 1795 break; 1796 } 1797 1798 DtInsertSubtable (ParentTable, Subtable); 1799 NodeLength += Subtable->Length; 1800 ContextIrptNumber++; 1801 } 1802 1803 IortSmmu->ContextInterruptCount = ContextIrptNumber; 1804 1805 /* Compile PMU interrupt array */ 1806 1807 PmuIrptNumber = 0; 1808 IortSmmu->PmuInterruptOffset = NodeLength; 1809 while (*PFieldList) 1810 { 1811 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c, 1812 &Subtable); 1813 if (ACPI_FAILURE (Status)) 1814 { 1815 return (Status); 1816 } 1817 1818 if (!Subtable) 1819 { 1820 break; 1821 } 1822 1823 DtInsertSubtable (ParentTable, Subtable); 1824 NodeLength += Subtable->Length; 1825 PmuIrptNumber++; 1826 } 1827 1828 IortSmmu->PmuInterruptCount = PmuIrptNumber; 1829 break; 1830 1831 case ACPI_IORT_NODE_SMMU_V3: 1832 1833 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4, 1834 &Subtable); 1835 if (ACPI_FAILURE (Status)) 1836 { 1837 return (Status); 1838 } 1839 1840 DtInsertSubtable (ParentTable, Subtable); 1841 NodeLength += Subtable->Length; 1842 break; 1843 1844 case ACPI_IORT_NODE_PMCG: 1845 1846 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5, 1847 &Subtable); 1848 if (ACPI_FAILURE (Status)) 1849 { 1850 return (Status); 1851 } 1852 1853 DtInsertSubtable (ParentTable, Subtable); 1854 NodeLength += Subtable->Length; 1855 break; 1856 1857 case ACPI_IORT_NODE_RMR: 1858 1859 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6, 1860 &Subtable); 1861 if (ACPI_FAILURE (Status)) 1862 { 1863 return (Status); 1864 } 1865 1866 DtInsertSubtable (ParentTable, Subtable); 1867 IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer); 1868 NodeLength += Subtable->Length; 1869 1870 /* Compile RMR Descriptors */ 1871 1872 RmrCount = 0; 1873 IortRmr->RmrOffset = NodeLength; 1874 while (*PFieldList) 1875 { 1876 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a, 1877 &Subtable); 1878 if (ACPI_FAILURE (Status)) 1879 { 1880 return (Status); 1881 } 1882 1883 if (!Subtable) 1884 { 1885 break; 1886 } 1887 1888 DtInsertSubtable (ParentTable, Subtable); 1889 NodeLength += sizeof (ACPI_IORT_RMR_DESC); 1890 RmrCount++; 1891 } 1892 1893 IortRmr->RmrCount = RmrCount; 1894 break; 1895 1896 default: 1897 1898 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT"); 1899 return (AE_ERROR); 1900 } 1901 1902 /* Compile Array of ID mappings */ 1903 1904 IortNode->MappingOffset = NodeLength; 1905 IdMappingNumber = 0; 1906 while (*PFieldList) 1907 { 1908 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap, 1909 &Subtable); 1910 if (ACPI_FAILURE (Status)) 1911 { 1912 return (Status); 1913 } 1914 1915 if (!Subtable) 1916 { 1917 break; 1918 } 1919 1920 DtInsertSubtable (ParentTable, Subtable); 1921 NodeLength += sizeof (ACPI_IORT_ID_MAPPING); 1922 IdMappingNumber++; 1923 } 1924 1925 IortNode->MappingCount = IdMappingNumber; 1926 if (!IdMappingNumber) 1927 { 1928 IortNode->MappingOffset = 0; 1929 } 1930 1931 /* 1932 * Node length can be determined by DT_LENGTH option 1933 * IortNode->Length = NodeLength; 1934 */ 1935 DtPopSubtable (); 1936 ParentTable = DtPeekSubtable (); 1937 NodeNumber++; 1938 } 1939 1940 Iort->NodeCount = NodeNumber; 1941 return (AE_OK); 1942 } 1943 1944 1945 /****************************************************************************** 1946 * 1947 * FUNCTION: DtCompileIvrs 1948 * 1949 * PARAMETERS: List - Current field list pointer 1950 * 1951 * RETURN: Status 1952 * 1953 * DESCRIPTION: Compile IVRS. 1954 * 1955 *****************************************************************************/ 1956 1957 ACPI_STATUS 1958 DtCompileIvrs ( 1959 void **List) 1960 { 1961 ACPI_STATUS Status; 1962 DT_SUBTABLE *Subtable; 1963 DT_SUBTABLE *ParentTable; 1964 DT_FIELD **PFieldList = (DT_FIELD **) List; 1965 DT_FIELD *SubtableStart; 1966 ACPI_DMTABLE_INFO *InfoTable; 1967 ACPI_IVRS_HEADER *IvrsHeader; 1968 UINT8 EntryType; 1969 1970 1971 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs, 1972 &Subtable); 1973 if (ACPI_FAILURE (Status)) 1974 { 1975 return (Status); 1976 } 1977 1978 ParentTable = DtPeekSubtable (); 1979 DtInsertSubtable (ParentTable, Subtable); 1980 1981 while (*PFieldList) 1982 { 1983 SubtableStart = *PFieldList; 1984 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr, 1985 &Subtable); 1986 if (ACPI_FAILURE (Status)) 1987 { 1988 return (Status); 1989 } 1990 1991 ParentTable = DtPeekSubtable (); 1992 DtInsertSubtable (ParentTable, Subtable); 1993 DtPushSubtable (Subtable); 1994 1995 IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer); 1996 1997 switch (IvrsHeader->Type) 1998 { 1999 case ACPI_IVRS_TYPE_HARDWARE1: 2000 2001 InfoTable = AcpiDmTableInfoIvrs0; 2002 break; 2003 2004 case ACPI_IVRS_TYPE_HARDWARE2: 2005 2006 InfoTable = AcpiDmTableInfoIvrs01; 2007 break; 2008 2009 case ACPI_IVRS_TYPE_MEMORY1: 2010 case ACPI_IVRS_TYPE_MEMORY2: 2011 case ACPI_IVRS_TYPE_MEMORY3: 2012 2013 InfoTable = AcpiDmTableInfoIvrs1; 2014 break; 2015 2016 default: 2017 2018 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS"); 2019 return (AE_ERROR); 2020 } 2021 2022 Status = DtCompileTable (PFieldList, InfoTable, &Subtable); 2023 if (ACPI_FAILURE (Status)) 2024 { 2025 return (Status); 2026 } 2027 2028 ParentTable = DtPeekSubtable (); 2029 DtInsertSubtable (ParentTable, Subtable); 2030 2031 if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE1 || 2032 IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE2) 2033 { 2034 while (*PFieldList && 2035 !strcmp ((*PFieldList)->Name, "Entry Type")) 2036 { 2037 SubtableStart = *PFieldList; 2038 DtCompileInteger (&EntryType, *PFieldList, 1, 0); 2039 2040 switch (EntryType) 2041 { 2042 /* 4-byte device entries */ 2043 2044 case ACPI_IVRS_TYPE_PAD4: 2045 case ACPI_IVRS_TYPE_ALL: 2046 case ACPI_IVRS_TYPE_SELECT: 2047 case ACPI_IVRS_TYPE_START: 2048 case ACPI_IVRS_TYPE_END: 2049 2050 InfoTable = AcpiDmTableInfoIvrs4; 2051 break; 2052 2053 /* 8-byte entries, type A */ 2054 2055 case ACPI_IVRS_TYPE_ALIAS_SELECT: 2056 case ACPI_IVRS_TYPE_ALIAS_START: 2057 2058 InfoTable = AcpiDmTableInfoIvrs8a; 2059 break; 2060 2061 /* 8-byte entries, type B */ 2062 2063 case ACPI_IVRS_TYPE_PAD8: 2064 case ACPI_IVRS_TYPE_EXT_SELECT: 2065 case ACPI_IVRS_TYPE_EXT_START: 2066 2067 InfoTable = AcpiDmTableInfoIvrs8b; 2068 break; 2069 2070 /* 8-byte entries, type C */ 2071 2072 case ACPI_IVRS_TYPE_SPECIAL: 2073 2074 InfoTable = AcpiDmTableInfoIvrs8c; 2075 break; 2076 2077 default: 2078 2079 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, 2080 "IVRS Device Entry"); 2081 return (AE_ERROR); 2082 } 2083 2084 Status = DtCompileTable (PFieldList, InfoTable, 2085 &Subtable); 2086 if (ACPI_FAILURE (Status)) 2087 { 2088 return (Status); 2089 } 2090 2091 DtInsertSubtable (ParentTable, Subtable); 2092 } 2093 } 2094 2095 DtPopSubtable (); 2096 } 2097 2098 return (AE_OK); 2099 } 2100