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