Home | History | Annotate | Line # | Download | only in compiler
dttable1.c revision 1.1.1.2
      1 /******************************************************************************
      2  *
      3  * Module Name: dttable1.c - handling for specific ACPI tables
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 #include "dtcompiler.h"
     48 
     49 #define _COMPONENT          DT_COMPILER
     50         ACPI_MODULE_NAME    ("dttable1")
     51 
     52 
     53 static ACPI_DMTABLE_INFO           TableInfoAsfAddress[] =
     54 {
     55     {ACPI_DMT_BUFFER,   0,               "Addresses", 0},
     56     {ACPI_DMT_EXIT,     0,               NULL, 0}
     57 };
     58 
     59 static ACPI_DMTABLE_INFO           TableInfoDmarPciPath[] =
     60 {
     61     {ACPI_DMT_PCI_PATH, 0,               "PCI Path", 0},
     62     {ACPI_DMT_EXIT,     0,               NULL, 0}
     63 };
     64 
     65 
     66 /******************************************************************************
     67  *
     68  * FUNCTION:    DtCompileAsf
     69  *
     70  * PARAMETERS:  List                - Current field list pointer
     71  *
     72  * RETURN:      Status
     73  *
     74  * DESCRIPTION: Compile ASF!.
     75  *
     76  *****************************************************************************/
     77 
     78 ACPI_STATUS
     79 DtCompileAsf (
     80     void                    **List)
     81 {
     82     ACPI_ASF_INFO           *AsfTable;
     83     DT_SUBTABLE             *Subtable;
     84     DT_SUBTABLE             *ParentTable;
     85     ACPI_DMTABLE_INFO       *InfoTable;
     86     ACPI_DMTABLE_INFO       *DataInfoTable = NULL;
     87     UINT32                  DataCount = 0;
     88     ACPI_STATUS             Status;
     89     UINT32                  i;
     90     DT_FIELD                **PFieldList = (DT_FIELD **) List;
     91     DT_FIELD                *SubtableStart;
     92 
     93 
     94     while (*PFieldList)
     95     {
     96         SubtableStart = *PFieldList;
     97         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
     98             &Subtable, TRUE);
     99         if (ACPI_FAILURE (Status))
    100         {
    101             return (Status);
    102         }
    103 
    104         ParentTable = DtPeekSubtable ();
    105         DtInsertSubtable (ParentTable, Subtable);
    106         DtPushSubtable (Subtable);
    107 
    108         AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
    109 
    110         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
    111         {
    112         case ACPI_ASF_TYPE_INFO:
    113 
    114             InfoTable = AcpiDmTableInfoAsf0;
    115             break;
    116 
    117         case ACPI_ASF_TYPE_ALERT:
    118 
    119             InfoTable = AcpiDmTableInfoAsf1;
    120             break;
    121 
    122         case ACPI_ASF_TYPE_CONTROL:
    123 
    124             InfoTable = AcpiDmTableInfoAsf2;
    125             break;
    126 
    127         case ACPI_ASF_TYPE_BOOT:
    128 
    129             InfoTable = AcpiDmTableInfoAsf3;
    130             break;
    131 
    132         case ACPI_ASF_TYPE_ADDRESS:
    133 
    134             InfoTable = AcpiDmTableInfoAsf4;
    135             break;
    136 
    137         default:
    138 
    139             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
    140             return (AE_ERROR);
    141         }
    142 
    143         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
    144         if (ACPI_FAILURE (Status))
    145         {
    146             return (Status);
    147         }
    148 
    149         ParentTable = DtPeekSubtable ();
    150         DtInsertSubtable (ParentTable, Subtable);
    151 
    152         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
    153         {
    154         case ACPI_ASF_TYPE_INFO:
    155 
    156             DataInfoTable = NULL;
    157             break;
    158 
    159         case ACPI_ASF_TYPE_ALERT:
    160 
    161             DataInfoTable = AcpiDmTableInfoAsf1a;
    162             DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
    163                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
    164                     sizeof (ACPI_ASF_HEADER)))->Alerts;
    165             break;
    166 
    167         case ACPI_ASF_TYPE_CONTROL:
    168 
    169             DataInfoTable = AcpiDmTableInfoAsf2a;
    170             DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
    171                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
    172                     sizeof (ACPI_ASF_HEADER)))->Controls;
    173             break;
    174 
    175         case ACPI_ASF_TYPE_BOOT:
    176 
    177             DataInfoTable = NULL;
    178             break;
    179 
    180         case ACPI_ASF_TYPE_ADDRESS:
    181 
    182             DataInfoTable = TableInfoAsfAddress;
    183             DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
    184                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
    185                     sizeof (ACPI_ASF_HEADER)))->Devices;
    186             break;
    187 
    188         default:
    189 
    190             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
    191             return (AE_ERROR);
    192         }
    193 
    194         if (DataInfoTable)
    195         {
    196             switch (AsfTable->Header.Type & 0x7F)
    197             {
    198             case ACPI_ASF_TYPE_ADDRESS:
    199 
    200                 while (DataCount > 0)
    201                 {
    202                     Status = DtCompileTable (PFieldList, DataInfoTable,
    203                         &Subtable, TRUE);
    204                     if (ACPI_FAILURE (Status))
    205                     {
    206                         return (Status);
    207                     }
    208 
    209                     DtInsertSubtable (ParentTable, Subtable);
    210                     DataCount = DataCount - Subtable->Length;
    211                 }
    212                 break;
    213 
    214             default:
    215 
    216                 for (i = 0; i < DataCount; i++)
    217                 {
    218                     Status = DtCompileTable (PFieldList, DataInfoTable,
    219                         &Subtable, TRUE);
    220                     if (ACPI_FAILURE (Status))
    221                     {
    222                         return (Status);
    223                     }
    224 
    225                     DtInsertSubtable (ParentTable, Subtable);
    226                 }
    227                 break;
    228             }
    229         }
    230 
    231         DtPopSubtable ();
    232     }
    233 
    234     return (AE_OK);
    235 }
    236 
    237 
    238 /******************************************************************************
    239  *
    240  * FUNCTION:    DtCompileCpep
    241  *
    242  * PARAMETERS:  List                - Current field list pointer
    243  *
    244  * RETURN:      Status
    245  *
    246  * DESCRIPTION: Compile CPEP.
    247  *
    248  *****************************************************************************/
    249 
    250 ACPI_STATUS
    251 DtCompileCpep (
    252     void                    **List)
    253 {
    254     ACPI_STATUS             Status;
    255 
    256 
    257     Status = DtCompileTwoSubtables (List,
    258         AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
    259     return (Status);
    260 }
    261 
    262 
    263 /******************************************************************************
    264  *
    265  * FUNCTION:    DtCompileCsrt
    266  *
    267  * PARAMETERS:  List                - Current field list pointer
    268  *
    269  * RETURN:      Status
    270  *
    271  * DESCRIPTION: Compile CSRT.
    272  *
    273  *****************************************************************************/
    274 
    275 ACPI_STATUS
    276 DtCompileCsrt (
    277     void                    **List)
    278 {
    279     ACPI_STATUS             Status = AE_OK;
    280     DT_SUBTABLE             *Subtable;
    281     DT_SUBTABLE             *ParentTable;
    282     DT_FIELD                **PFieldList = (DT_FIELD **) List;
    283     UINT32                  DescriptorCount;
    284     UINT32                  GroupLength;
    285 
    286 
    287     /* Subtables (Resource Groups) */
    288 
    289     ParentTable = DtPeekSubtable ();
    290     while (*PFieldList)
    291     {
    292         /* Resource group subtable */
    293 
    294         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
    295             &Subtable, TRUE);
    296         if (ACPI_FAILURE (Status))
    297         {
    298             return (Status);
    299         }
    300 
    301         /* Compute the number of resource descriptors */
    302 
    303         GroupLength =
    304             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
    305                 Subtable->Buffer))->Length -
    306             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
    307                 Subtable->Buffer))->SharedInfoLength -
    308             sizeof (ACPI_CSRT_GROUP);
    309 
    310         DescriptorCount = (GroupLength  /
    311             sizeof (ACPI_CSRT_DESCRIPTOR));
    312 
    313         DtInsertSubtable (ParentTable, Subtable);
    314         DtPushSubtable (Subtable);
    315         ParentTable = DtPeekSubtable ();
    316 
    317         /* Shared info subtable (One per resource group) */
    318 
    319         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
    320             &Subtable, TRUE);
    321         if (ACPI_FAILURE (Status))
    322         {
    323             return (Status);
    324         }
    325 
    326         DtInsertSubtable (ParentTable, Subtable);
    327 
    328         /* Sub-Subtables (Resource Descriptors) */
    329 
    330         while (*PFieldList && DescriptorCount)
    331         {
    332 
    333             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
    334                 &Subtable, TRUE);
    335             if (ACPI_FAILURE (Status))
    336             {
    337                 return (Status);
    338             }
    339 
    340             DtInsertSubtable (ParentTable, Subtable);
    341 
    342             DtPushSubtable (Subtable);
    343             ParentTable = DtPeekSubtable ();
    344             if (*PFieldList)
    345             {
    346                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
    347                     &Subtable, TRUE);
    348                 if (ACPI_FAILURE (Status))
    349                 {
    350                     return (Status);
    351                 }
    352                 if (Subtable)
    353                 {
    354                     DtInsertSubtable (ParentTable, Subtable);
    355                 }
    356             }
    357 
    358             DtPopSubtable ();
    359             ParentTable = DtPeekSubtable ();
    360             DescriptorCount--;
    361         }
    362 
    363         DtPopSubtable ();
    364         ParentTable = DtPeekSubtable ();
    365     }
    366 
    367     return (Status);
    368 }
    369 
    370 
    371 /******************************************************************************
    372  *
    373  * FUNCTION:    DtCompileDbg2
    374  *
    375  * PARAMETERS:  List                - Current field list pointer
    376  *
    377  * RETURN:      Status
    378  *
    379  * DESCRIPTION: Compile DBG2.
    380  *
    381  *****************************************************************************/
    382 
    383 ACPI_STATUS
    384 DtCompileDbg2 (
    385     void                    **List)
    386 {
    387     ACPI_STATUS             Status;
    388     DT_SUBTABLE             *Subtable;
    389     DT_SUBTABLE             *ParentTable;
    390     DT_FIELD                **PFieldList = (DT_FIELD **) List;
    391     UINT32                  SubtableCount;
    392     ACPI_DBG2_HEADER        *Dbg2Header;
    393     ACPI_DBG2_DEVICE        *DeviceInfo;
    394     UINT16                  CurrentOffset;
    395     UINT32                  i;
    396 
    397 
    398     /* Main table */
    399 
    400     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable, TRUE);
    401     if (ACPI_FAILURE (Status))
    402     {
    403         return (Status);
    404     }
    405 
    406     ParentTable = DtPeekSubtable ();
    407     DtInsertSubtable (ParentTable, Subtable);
    408 
    409     /* Main table fields */
    410 
    411     Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
    412     Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
    413         ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
    414 
    415     SubtableCount = Dbg2Header->InfoCount;
    416     DtPushSubtable (Subtable);
    417 
    418     /* Process all Device Information subtables (Count = InfoCount) */
    419 
    420     while (*PFieldList && SubtableCount)
    421     {
    422         /* Subtable: Debug Device Information */
    423 
    424         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
    425             &Subtable, TRUE);
    426         if (ACPI_FAILURE (Status))
    427         {
    428             return (Status);
    429         }
    430 
    431         DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
    432         CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
    433 
    434         ParentTable = DtPeekSubtable ();
    435         DtInsertSubtable (ParentTable, Subtable);
    436         DtPushSubtable (Subtable);
    437 
    438         ParentTable = DtPeekSubtable ();
    439 
    440         /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
    441 
    442         DeviceInfo->BaseAddressOffset = CurrentOffset;
    443         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
    444         {
    445             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
    446                 &Subtable, TRUE);
    447             if (ACPI_FAILURE (Status))
    448             {
    449                 return (Status);
    450             }
    451 
    452             CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
    453             DtInsertSubtable (ParentTable, Subtable);
    454         }
    455 
    456         /* AddressSize array (Required, size = RegisterCount) */
    457 
    458         DeviceInfo->AddressSizeOffset = CurrentOffset;
    459         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
    460         {
    461             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
    462                 &Subtable, TRUE);
    463             if (ACPI_FAILURE (Status))
    464             {
    465                 return (Status);
    466             }
    467 
    468             CurrentOffset += (UINT16) sizeof (UINT32);
    469             DtInsertSubtable (ParentTable, Subtable);
    470         }
    471 
    472         /* NamespaceString device identifier (Required, size = NamePathLength) */
    473 
    474         DeviceInfo->NamepathOffset = CurrentOffset;
    475         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
    476             &Subtable, TRUE);
    477         if (ACPI_FAILURE (Status))
    478         {
    479             return (Status);
    480         }
    481 
    482         /* Update the device info header */
    483 
    484         DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
    485         CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
    486         DtInsertSubtable (ParentTable, Subtable);
    487 
    488         /* OemData - Variable-length data (Optional, size = OemDataLength) */
    489 
    490         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
    491             &Subtable, TRUE);
    492         if (ACPI_FAILURE (Status))
    493         {
    494             return (Status);
    495         }
    496 
    497         /* Update the device info header (zeros if no OEM data present) */
    498 
    499         DeviceInfo->OemDataOffset = 0;
    500         DeviceInfo->OemDataLength = 0;
    501 
    502         /* Optional subtable (OemData) */
    503 
    504         if (Subtable && Subtable->Length)
    505         {
    506             DeviceInfo->OemDataOffset = CurrentOffset;
    507             DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
    508 
    509             DtInsertSubtable (ParentTable, Subtable);
    510         }
    511 
    512         SubtableCount--;
    513         DtPopSubtable (); /* Get next Device Information subtable */
    514     }
    515 
    516     DtPopSubtable ();
    517     return (AE_OK);
    518 }
    519 
    520 
    521 /******************************************************************************
    522  *
    523  * FUNCTION:    DtCompileDmar
    524  *
    525  * PARAMETERS:  List                - Current field list pointer
    526  *
    527  * RETURN:      Status
    528  *
    529  * DESCRIPTION: Compile DMAR.
    530  *
    531  *****************************************************************************/
    532 
    533 ACPI_STATUS
    534 DtCompileDmar (
    535     void                    **List)
    536 {
    537     ACPI_STATUS             Status;
    538     DT_SUBTABLE             *Subtable;
    539     DT_SUBTABLE             *ParentTable;
    540     DT_FIELD                **PFieldList = (DT_FIELD **) List;
    541     DT_FIELD                *SubtableStart;
    542     ACPI_DMTABLE_INFO       *InfoTable;
    543     ACPI_DMAR_HEADER        *DmarHeader;
    544     ACPI_DMAR_DEVICE_SCOPE  *DmarDeviceScope;
    545     UINT32                  DeviceScopeLength;
    546     UINT32                  PciPathLength;
    547 
    548 
    549     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable, TRUE);
    550     if (ACPI_FAILURE (Status))
    551     {
    552         return (Status);
    553     }
    554 
    555     ParentTable = DtPeekSubtable ();
    556     DtInsertSubtable (ParentTable, Subtable);
    557     DtPushSubtable (Subtable);
    558 
    559     while (*PFieldList)
    560     {
    561         /* DMAR Header */
    562 
    563         SubtableStart = *PFieldList;
    564         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
    565             &Subtable, TRUE);
    566         if (ACPI_FAILURE (Status))
    567         {
    568             return (Status);
    569         }
    570 
    571         ParentTable = DtPeekSubtable ();
    572         DtInsertSubtable (ParentTable, Subtable);
    573         DtPushSubtable (Subtable);
    574 
    575         DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
    576 
    577         switch (DmarHeader->Type)
    578         {
    579         case ACPI_DMAR_TYPE_HARDWARE_UNIT:
    580 
    581             InfoTable = AcpiDmTableInfoDmar0;
    582             break;
    583 
    584         case ACPI_DMAR_TYPE_RESERVED_MEMORY:
    585 
    586             InfoTable = AcpiDmTableInfoDmar1;
    587             break;
    588 
    589         case ACPI_DMAR_TYPE_ROOT_ATS:
    590 
    591             InfoTable = AcpiDmTableInfoDmar2;
    592             break;
    593 
    594         case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
    595 
    596             InfoTable = AcpiDmTableInfoDmar3;
    597             break;
    598 
    599         case ACPI_DMAR_TYPE_NAMESPACE:
    600 
    601             InfoTable = AcpiDmTableInfoDmar4;
    602             break;
    603 
    604         default:
    605 
    606             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
    607             return (AE_ERROR);
    608         }
    609 
    610         /* DMAR Subtable */
    611 
    612         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
    613         if (ACPI_FAILURE (Status))
    614         {
    615             return (Status);
    616         }
    617 
    618         ParentTable = DtPeekSubtable ();
    619         DtInsertSubtable (ParentTable, Subtable);
    620 
    621         /*
    622          * Optional Device Scope subtables
    623          */
    624         if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
    625             (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
    626         {
    627             /* These types do not support device scopes */
    628 
    629             DtPopSubtable ();
    630             continue;
    631         }
    632 
    633         DtPushSubtable (Subtable);
    634         DeviceScopeLength = DmarHeader->Length - Subtable->Length -
    635             ParentTable->Length;
    636         while (DeviceScopeLength)
    637         {
    638             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
    639                 &Subtable, FALSE);
    640             if (Status == AE_NOT_FOUND)
    641             {
    642                 break;
    643             }
    644 
    645             ParentTable = DtPeekSubtable ();
    646             DtInsertSubtable (ParentTable, Subtable);
    647             DtPushSubtable (Subtable);
    648 
    649             DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
    650 
    651             /* Optional PCI Paths */
    652 
    653             PciPathLength = DmarDeviceScope->Length - Subtable->Length;
    654             while (PciPathLength)
    655             {
    656                 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
    657                     &Subtable, FALSE);
    658                 if (Status == AE_NOT_FOUND)
    659                 {
    660                     DtPopSubtable ();
    661                     break;
    662                 }
    663 
    664                 ParentTable = DtPeekSubtable ();
    665                 DtInsertSubtable (ParentTable, Subtable);
    666                 PciPathLength -= Subtable->Length;
    667             }
    668 
    669             DtPopSubtable ();
    670             DeviceScopeLength -= DmarDeviceScope->Length;
    671         }
    672 
    673         DtPopSubtable ();
    674         DtPopSubtable ();
    675     }
    676 
    677     return (AE_OK);
    678 }
    679 
    680 
    681 /******************************************************************************
    682  *
    683  * FUNCTION:    DtCompileDrtm
    684  *
    685  * PARAMETERS:  List                - Current field list pointer
    686  *
    687  * RETURN:      Status
    688  *
    689  * DESCRIPTION: Compile DRTM.
    690  *
    691  *****************************************************************************/
    692 
    693 ACPI_STATUS
    694 DtCompileDrtm (
    695     void                    **List)
    696 {
    697     ACPI_STATUS             Status;
    698     DT_SUBTABLE             *Subtable;
    699     DT_SUBTABLE             *ParentTable;
    700     DT_FIELD                **PFieldList = (DT_FIELD **) List;
    701     UINT32                  Count;
    702     /* ACPI_TABLE_DRTM         *Drtm; */
    703     ACPI_DRTM_VTABLE_LIST   *DrtmVtl;
    704     ACPI_DRTM_RESOURCE_LIST *DrtmRl;
    705     /* ACPI_DRTM_DPS_ID        *DrtmDps; */
    706 
    707 
    708     ParentTable = DtPeekSubtable ();
    709 
    710     /* Compile DRTM header */
    711 
    712     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
    713         &Subtable, TRUE);
    714     if (ACPI_FAILURE (Status))
    715     {
    716         return (Status);
    717     }
    718     DtInsertSubtable (ParentTable, Subtable);
    719 
    720     /*
    721      * Using ACPI_SUB_PTR, We needn't define a seperate structure. Care
    722      * should be taken to avoid accessing ACPI_TABLE_HADER fields.
    723      */
    724 #if 0
    725     Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
    726         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
    727 #endif
    728     /* Compile VTL */
    729 
    730     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
    731         &Subtable, TRUE);
    732     if (ACPI_FAILURE (Status))
    733     {
    734         return (Status);
    735     }
    736 
    737     DtInsertSubtable (ParentTable, Subtable);
    738     DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
    739 
    740     DtPushSubtable (Subtable);
    741     ParentTable = DtPeekSubtable ();
    742     Count = 0;
    743 
    744     while (*PFieldList)
    745     {
    746         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
    747             &Subtable, TRUE);
    748         if (ACPI_FAILURE (Status))
    749         {
    750             return (Status);
    751         }
    752         if (!Subtable)
    753         {
    754             break;
    755         }
    756         DtInsertSubtable (ParentTable, Subtable);
    757         Count++;
    758     }
    759 
    760     DrtmVtl->ValidatedTableCount = Count;
    761     DtPopSubtable ();
    762     ParentTable = DtPeekSubtable ();
    763 
    764     /* Compile RL */
    765 
    766     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
    767         &Subtable, TRUE);
    768     if (ACPI_FAILURE (Status))
    769     {
    770         return (Status);
    771     }
    772 
    773     DtInsertSubtable (ParentTable, Subtable);
    774     DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
    775 
    776     DtPushSubtable (Subtable);
    777     ParentTable = DtPeekSubtable ();
    778     Count = 0;
    779 
    780     while (*PFieldList)
    781     {
    782         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
    783             &Subtable, TRUE);
    784         if (ACPI_FAILURE (Status))
    785         {
    786             return (Status);
    787         }
    788 
    789         if (!Subtable)
    790         {
    791             break;
    792         }
    793 
    794         DtInsertSubtable (ParentTable, Subtable);
    795         Count++;
    796     }
    797 
    798     DrtmRl->ResourceCount = Count;
    799     DtPopSubtable ();
    800     ParentTable = DtPeekSubtable ();
    801 
    802     /* Compile DPS */
    803 
    804     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
    805         &Subtable, TRUE);
    806     if (ACPI_FAILURE (Status))
    807     {
    808         return (Status);
    809     }
    810     DtInsertSubtable (ParentTable, Subtable);
    811     /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
    812 
    813 
    814     return (AE_OK);
    815 }
    816 
    817 
    818 /******************************************************************************
    819  *
    820  * FUNCTION:    DtCompileEinj
    821  *
    822  * PARAMETERS:  List                - Current field list pointer
    823  *
    824  * RETURN:      Status
    825  *
    826  * DESCRIPTION: Compile EINJ.
    827  *
    828  *****************************************************************************/
    829 
    830 ACPI_STATUS
    831 DtCompileEinj (
    832     void                    **List)
    833 {
    834     ACPI_STATUS             Status;
    835 
    836 
    837     Status = DtCompileTwoSubtables (List,
    838         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
    839     return (Status);
    840 }
    841 
    842 
    843 /******************************************************************************
    844  *
    845  * FUNCTION:    DtCompileErst
    846  *
    847  * PARAMETERS:  List                - Current field list pointer
    848  *
    849  * RETURN:      Status
    850  *
    851  * DESCRIPTION: Compile ERST.
    852  *
    853  *****************************************************************************/
    854 
    855 ACPI_STATUS
    856 DtCompileErst (
    857     void                    **List)
    858 {
    859     ACPI_STATUS             Status;
    860 
    861 
    862     Status = DtCompileTwoSubtables (List,
    863         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
    864     return (Status);
    865 }
    866 
    867 
    868 /******************************************************************************
    869  *
    870  * FUNCTION:    DtCompileGtdt
    871  *
    872  * PARAMETERS:  List                - Current field list pointer
    873  *
    874  * RETURN:      Status
    875  *
    876  * DESCRIPTION: Compile GTDT.
    877  *
    878  *****************************************************************************/
    879 
    880 ACPI_STATUS
    881 DtCompileGtdt (
    882     void                    **List)
    883 {
    884     ACPI_STATUS             Status;
    885     DT_SUBTABLE             *Subtable;
    886     DT_SUBTABLE             *ParentTable;
    887     DT_FIELD                **PFieldList = (DT_FIELD **) List;
    888     DT_FIELD                *SubtableStart;
    889     ACPI_SUBTABLE_HEADER    *GtdtHeader;
    890     ACPI_DMTABLE_INFO       *InfoTable;
    891     UINT32                  GtCount;
    892 
    893 
    894     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
    895         &Subtable, TRUE);
    896     if (ACPI_FAILURE (Status))
    897     {
    898         return (Status);
    899     }
    900 
    901     ParentTable = DtPeekSubtable ();
    902     DtInsertSubtable (ParentTable, Subtable);
    903 
    904     while (*PFieldList)
    905     {
    906         SubtableStart = *PFieldList;
    907         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
    908             &Subtable, TRUE);
    909         if (ACPI_FAILURE (Status))
    910         {
    911             return (Status);
    912         }
    913 
    914         ParentTable = DtPeekSubtable ();
    915         DtInsertSubtable (ParentTable, Subtable);
    916         DtPushSubtable (Subtable);
    917 
    918         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
    919 
    920         switch (GtdtHeader->Type)
    921         {
    922         case ACPI_GTDT_TYPE_TIMER_BLOCK:
    923 
    924             InfoTable = AcpiDmTableInfoGtdt0;
    925             break;
    926 
    927         case ACPI_GTDT_TYPE_WATCHDOG:
    928 
    929             InfoTable = AcpiDmTableInfoGtdt1;
    930             break;
    931 
    932         default:
    933 
    934             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
    935             return (AE_ERROR);
    936         }
    937 
    938         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
    939         if (ACPI_FAILURE (Status))
    940         {
    941             return (Status);
    942         }
    943 
    944         ParentTable = DtPeekSubtable ();
    945         DtInsertSubtable (ParentTable, Subtable);
    946 
    947         /*
    948          * Additional GT block subtable data
    949          */
    950 
    951         switch (GtdtHeader->Type)
    952         {
    953         case ACPI_GTDT_TYPE_TIMER_BLOCK:
    954 
    955             DtPushSubtable (Subtable);
    956             ParentTable = DtPeekSubtable ();
    957 
    958             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
    959                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
    960 
    961             while (GtCount)
    962             {
    963                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
    964                     &Subtable, TRUE);
    965                 if (ACPI_FAILURE (Status))
    966                 {
    967                     return (Status);
    968                 }
    969 
    970                 DtInsertSubtable (ParentTable, Subtable);
    971                 GtCount--;
    972             }
    973 
    974             DtPopSubtable ();
    975             break;
    976 
    977         default:
    978 
    979             break;
    980         }
    981 
    982         DtPopSubtable ();
    983     }
    984 
    985     return (AE_OK);
    986 }
    987 
    988 
    989 /******************************************************************************
    990  *
    991  * FUNCTION:    DtCompileFpdt
    992  *
    993  * PARAMETERS:  List                - Current field list pointer
    994  *
    995  * RETURN:      Status
    996  *
    997  * DESCRIPTION: Compile FPDT.
    998  *
    999  *****************************************************************************/
   1000 
   1001 ACPI_STATUS
   1002 DtCompileFpdt (
   1003     void                    **List)
   1004 {
   1005     ACPI_STATUS             Status;
   1006     ACPI_FPDT_HEADER        *FpdtHeader;
   1007     DT_SUBTABLE             *Subtable;
   1008     DT_SUBTABLE             *ParentTable;
   1009     ACPI_DMTABLE_INFO       *InfoTable;
   1010     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1011     DT_FIELD                *SubtableStart;
   1012 
   1013 
   1014     while (*PFieldList)
   1015     {
   1016         SubtableStart = *PFieldList;
   1017         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
   1018             &Subtable, TRUE);
   1019         if (ACPI_FAILURE (Status))
   1020         {
   1021             return (Status);
   1022         }
   1023 
   1024         ParentTable = DtPeekSubtable ();
   1025         DtInsertSubtable (ParentTable, Subtable);
   1026         DtPushSubtable (Subtable);
   1027 
   1028         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
   1029 
   1030         switch (FpdtHeader->Type)
   1031         {
   1032         case ACPI_FPDT_TYPE_BOOT:
   1033 
   1034             InfoTable = AcpiDmTableInfoFpdt0;
   1035             break;
   1036 
   1037         case ACPI_FPDT_TYPE_S3PERF:
   1038 
   1039             InfoTable = AcpiDmTableInfoFpdt1;
   1040             break;
   1041 
   1042         default:
   1043 
   1044             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
   1045             return (AE_ERROR);
   1046             break;
   1047         }
   1048 
   1049         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
   1050         if (ACPI_FAILURE (Status))
   1051         {
   1052             return (Status);
   1053         }
   1054 
   1055         ParentTable = DtPeekSubtable ();
   1056         DtInsertSubtable (ParentTable, Subtable);
   1057         DtPopSubtable ();
   1058     }
   1059 
   1060     return (AE_OK);
   1061 }
   1062 
   1063 
   1064 /******************************************************************************
   1065  *
   1066  * FUNCTION:    DtCompileHest
   1067  *
   1068  * PARAMETERS:  List                - Current field list pointer
   1069  *
   1070  * RETURN:      Status
   1071  *
   1072  * DESCRIPTION: Compile HEST.
   1073  *
   1074  *****************************************************************************/
   1075 
   1076 ACPI_STATUS
   1077 DtCompileHest (
   1078     void                    **List)
   1079 {
   1080     ACPI_STATUS             Status;
   1081     DT_SUBTABLE             *Subtable;
   1082     DT_SUBTABLE             *ParentTable;
   1083     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1084     DT_FIELD                *SubtableStart;
   1085     ACPI_DMTABLE_INFO       *InfoTable;
   1086     UINT16                  Type;
   1087     UINT32                  BankCount;
   1088 
   1089 
   1090     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
   1091         &Subtable, TRUE);
   1092     if (ACPI_FAILURE (Status))
   1093     {
   1094         return (Status);
   1095     }
   1096 
   1097     ParentTable = DtPeekSubtable ();
   1098     DtInsertSubtable (ParentTable, Subtable);
   1099 
   1100     while (*PFieldList)
   1101     {
   1102         /* Get subtable type */
   1103 
   1104         SubtableStart = *PFieldList;
   1105         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
   1106 
   1107         switch (Type)
   1108         {
   1109         case ACPI_HEST_TYPE_IA32_CHECK:
   1110 
   1111             InfoTable = AcpiDmTableInfoHest0;
   1112             break;
   1113 
   1114         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
   1115 
   1116             InfoTable = AcpiDmTableInfoHest1;
   1117             break;
   1118 
   1119         case ACPI_HEST_TYPE_IA32_NMI:
   1120 
   1121             InfoTable = AcpiDmTableInfoHest2;
   1122             break;
   1123 
   1124         case ACPI_HEST_TYPE_AER_ROOT_PORT:
   1125 
   1126             InfoTable = AcpiDmTableInfoHest6;
   1127             break;
   1128 
   1129         case ACPI_HEST_TYPE_AER_ENDPOINT:
   1130 
   1131             InfoTable = AcpiDmTableInfoHest7;
   1132             break;
   1133 
   1134         case ACPI_HEST_TYPE_AER_BRIDGE:
   1135 
   1136             InfoTable = AcpiDmTableInfoHest8;
   1137             break;
   1138 
   1139         case ACPI_HEST_TYPE_GENERIC_ERROR:
   1140 
   1141             InfoTable = AcpiDmTableInfoHest9;
   1142             break;
   1143 
   1144         default:
   1145 
   1146             /* Cannot continue on unknown type */
   1147 
   1148             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
   1149             return (AE_ERROR);
   1150         }
   1151 
   1152         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
   1153         if (ACPI_FAILURE (Status))
   1154         {
   1155             return (Status);
   1156         }
   1157 
   1158         DtInsertSubtable (ParentTable, Subtable);
   1159 
   1160         /*
   1161          * Additional subtable data - IA32 Error Bank(s)
   1162          */
   1163         BankCount = 0;
   1164         switch (Type)
   1165         {
   1166         case ACPI_HEST_TYPE_IA32_CHECK:
   1167 
   1168             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
   1169                 Subtable->Buffer))->NumHardwareBanks;
   1170             break;
   1171 
   1172         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
   1173 
   1174             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
   1175                 Subtable->Buffer))->NumHardwareBanks;
   1176             break;
   1177 
   1178         default:
   1179 
   1180             break;
   1181         }
   1182 
   1183         while (BankCount)
   1184         {
   1185             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
   1186                 &Subtable, TRUE);
   1187             if (ACPI_FAILURE (Status))
   1188             {
   1189                 return (Status);
   1190             }
   1191 
   1192             DtInsertSubtable (ParentTable, Subtable);
   1193             BankCount--;
   1194         }
   1195     }
   1196 
   1197     return (AE_OK);
   1198 }
   1199 
   1200 
   1201 /******************************************************************************
   1202  *
   1203  * FUNCTION:    DtCompileIort
   1204  *
   1205  * PARAMETERS:  List                - Current field list pointer
   1206  *
   1207  * RETURN:      Status
   1208  *
   1209  * DESCRIPTION: Compile IORT.
   1210  *
   1211  *****************************************************************************/
   1212 
   1213 ACPI_STATUS
   1214 DtCompileIort (
   1215     void                    **List)
   1216 {
   1217     ACPI_STATUS             Status;
   1218     DT_SUBTABLE             *Subtable;
   1219     DT_SUBTABLE             *ParentTable;
   1220     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1221     DT_FIELD                *SubtableStart;
   1222     ACPI_TABLE_IORT         *Iort;
   1223     ACPI_IORT_NODE          *IortNode;
   1224     ACPI_IORT_ITS_GROUP     *IortItsGroup;
   1225     ACPI_IORT_SMMU          *IortSmmu;
   1226     UINT32                  NodeNumber;
   1227     UINT32                  NodeLength;
   1228     UINT32                  IdMappingNumber;
   1229     UINT32                  ItsNumber;
   1230     UINT32                  ContextIrptNumber;
   1231     UINT32                  PmuIrptNumber;
   1232     UINT32                  PaddingLength;
   1233 
   1234 
   1235     ParentTable = DtPeekSubtable ();
   1236 
   1237     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
   1238         &Subtable, TRUE);
   1239     if (ACPI_FAILURE (Status))
   1240     {
   1241         return (Status);
   1242     }
   1243     DtInsertSubtable (ParentTable, Subtable);
   1244 
   1245     /*
   1246      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
   1247      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
   1248      */
   1249     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
   1250         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
   1251 
   1252     /*
   1253      * OptionalPadding - Variable-length data
   1254      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
   1255      * Optionally allows the generic data types to be used for filling
   1256      * this field.
   1257      */
   1258     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
   1259     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
   1260         &Subtable, TRUE);
   1261     if (ACPI_FAILURE (Status))
   1262     {
   1263         return (Status);
   1264     }
   1265     if (Subtable)
   1266     {
   1267         DtInsertSubtable (ParentTable, Subtable);
   1268         Iort->NodeOffset += Subtable->Length;
   1269     }
   1270     else
   1271     {
   1272         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
   1273             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
   1274         if (ACPI_FAILURE (Status))
   1275         {
   1276             return (Status);
   1277         }
   1278         Iort->NodeOffset += PaddingLength;
   1279     }
   1280 
   1281     NodeNumber = 0;
   1282     while (*PFieldList)
   1283     {
   1284         SubtableStart = *PFieldList;
   1285         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
   1286             &Subtable, TRUE);
   1287         if (ACPI_FAILURE (Status))
   1288         {
   1289             return (Status);
   1290         }
   1291 
   1292         DtInsertSubtable (ParentTable, Subtable);
   1293         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
   1294         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
   1295 
   1296         DtPushSubtable (Subtable);
   1297         ParentTable = DtPeekSubtable ();
   1298 
   1299         switch (IortNode->Type)
   1300         {
   1301         case ACPI_IORT_NODE_ITS_GROUP:
   1302 
   1303             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
   1304                 &Subtable, TRUE);
   1305             if (ACPI_FAILURE (Status))
   1306             {
   1307                 return (Status);
   1308             }
   1309 
   1310             DtInsertSubtable (ParentTable, Subtable);
   1311             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
   1312             NodeLength += Subtable->Length;
   1313 
   1314             ItsNumber = 0;
   1315             while (*PFieldList)
   1316             {
   1317                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
   1318                     &Subtable, TRUE);
   1319                 if (ACPI_FAILURE (Status))
   1320                 {
   1321                     return (Status);
   1322                 }
   1323                 if (!Subtable)
   1324                 {
   1325                     break;
   1326                 }
   1327 
   1328                 DtInsertSubtable (ParentTable, Subtable);
   1329                 NodeLength += Subtable->Length;
   1330                 ItsNumber++;
   1331             }
   1332 
   1333             IortItsGroup->ItsCount = ItsNumber;
   1334             break;
   1335 
   1336         case ACPI_IORT_NODE_NAMED_COMPONENT:
   1337 
   1338             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
   1339                 &Subtable, TRUE);
   1340             if (ACPI_FAILURE (Status))
   1341             {
   1342                 return (Status);
   1343             }
   1344 
   1345             DtInsertSubtable (ParentTable, Subtable);
   1346             NodeLength += Subtable->Length;
   1347 
   1348             /*
   1349              * Padding - Variable-length data
   1350              * Optionally allows the offset of the ID mappings to be used
   1351              * for filling this field.
   1352              */
   1353             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
   1354                 &Subtable, TRUE);
   1355             if (ACPI_FAILURE (Status))
   1356             {
   1357                 return (Status);
   1358             }
   1359 
   1360             if (Subtable)
   1361             {
   1362                 DtInsertSubtable (ParentTable, Subtable);
   1363                 NodeLength += Subtable->Length;
   1364             }
   1365             else
   1366             {
   1367                 if (NodeLength > IortNode->MappingOffset)
   1368                 {
   1369                     return (AE_BAD_DATA);
   1370                 }
   1371 
   1372                 if (NodeLength < IortNode->MappingOffset)
   1373                 {
   1374                     Status = DtCompilePadding (
   1375                         IortNode->MappingOffset - NodeLength,
   1376                         &Subtable);
   1377                     if (ACPI_FAILURE (Status))
   1378                     {
   1379                         return (Status);
   1380                     }
   1381 
   1382                     DtInsertSubtable (ParentTable, Subtable);
   1383                     NodeLength = IortNode->MappingOffset;
   1384                 }
   1385             }
   1386             break;
   1387 
   1388         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
   1389 
   1390             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
   1391                 &Subtable, TRUE);
   1392             if (ACPI_FAILURE (Status))
   1393             {
   1394                 return (Status);
   1395             }
   1396 
   1397             DtInsertSubtable (ParentTable, Subtable);
   1398             NodeLength += Subtable->Length;
   1399             break;
   1400 
   1401         case ACPI_IORT_NODE_SMMU:
   1402 
   1403             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
   1404                 &Subtable, TRUE);
   1405             if (ACPI_FAILURE (Status))
   1406             {
   1407                 return (Status);
   1408             }
   1409 
   1410             DtInsertSubtable (ParentTable, Subtable);
   1411             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
   1412             NodeLength += Subtable->Length;
   1413 
   1414             /* Compile global interrupt array */
   1415 
   1416             IortSmmu->GlobalInterruptOffset = NodeLength;
   1417             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
   1418                 &Subtable, TRUE);
   1419             if (ACPI_FAILURE (Status))
   1420             {
   1421                 return (Status);
   1422             }
   1423 
   1424             DtInsertSubtable (ParentTable, Subtable);
   1425             NodeLength += Subtable->Length;
   1426 
   1427             /* Compile context interrupt array */
   1428 
   1429             ContextIrptNumber = 0;
   1430             IortSmmu->ContextInterruptOffset = NodeLength;
   1431             while (*PFieldList)
   1432             {
   1433                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
   1434                     &Subtable, TRUE);
   1435                 if (ACPI_FAILURE (Status))
   1436                 {
   1437                     return (Status);
   1438                 }
   1439 
   1440                 if (!Subtable)
   1441                 {
   1442                     break;
   1443                 }
   1444 
   1445                 DtInsertSubtable (ParentTable, Subtable);
   1446                 NodeLength += Subtable->Length;
   1447                 ContextIrptNumber++;
   1448             }
   1449 
   1450             IortSmmu->ContextInterruptCount = ContextIrptNumber;
   1451 
   1452             /* Compile PMU interrupt array */
   1453 
   1454             PmuIrptNumber = 0;
   1455             IortSmmu->PmuInterruptOffset = NodeLength;
   1456             while (*PFieldList)
   1457             {
   1458                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
   1459                     &Subtable, TRUE);
   1460                 if (ACPI_FAILURE (Status))
   1461                 {
   1462                     return (Status);
   1463                 }
   1464 
   1465                 if (!Subtable)
   1466                 {
   1467                     break;
   1468                 }
   1469 
   1470                 DtInsertSubtable (ParentTable, Subtable);
   1471                 NodeLength += Subtable->Length;
   1472                 PmuIrptNumber++;
   1473             }
   1474 
   1475             IortSmmu->PmuInterruptCount = PmuIrptNumber;
   1476             break;
   1477 
   1478         case ACPI_IORT_NODE_SMMU_V3:
   1479 
   1480             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
   1481                 &Subtable, TRUE);
   1482             if (ACPI_FAILURE (Status))
   1483             {
   1484                 return (Status);
   1485             }
   1486 
   1487             DtInsertSubtable (ParentTable, Subtable);
   1488             NodeLength += Subtable->Length;
   1489             break;
   1490 
   1491         default:
   1492 
   1493             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
   1494             return (AE_ERROR);
   1495         }
   1496 
   1497         /* Compile Array of ID mappings */
   1498 
   1499         IortNode->MappingOffset = NodeLength;
   1500         IdMappingNumber = 0;
   1501         while (*PFieldList)
   1502         {
   1503             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
   1504                 &Subtable, TRUE);
   1505             if (ACPI_FAILURE (Status))
   1506             {
   1507                 return (Status);
   1508             }
   1509 
   1510             if (!Subtable)
   1511             {
   1512                 break;
   1513             }
   1514 
   1515             DtInsertSubtable (ParentTable, Subtable);
   1516             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
   1517             IdMappingNumber++;
   1518         }
   1519 
   1520         IortNode->MappingCount = IdMappingNumber;
   1521 
   1522         /*
   1523          * Node length can be determined by DT_LENGTH option
   1524          * IortNode->Length = NodeLength;
   1525          */
   1526         DtPopSubtable ();
   1527         ParentTable = DtPeekSubtable ();
   1528         NodeNumber++;
   1529     }
   1530 
   1531     Iort->NodeCount = NodeNumber;
   1532     return (AE_OK);
   1533 }
   1534 
   1535 
   1536 /******************************************************************************
   1537  *
   1538  * FUNCTION:    DtCompileIvrs
   1539  *
   1540  * PARAMETERS:  List                - Current field list pointer
   1541  *
   1542  * RETURN:      Status
   1543  *
   1544  * DESCRIPTION: Compile IVRS.
   1545  *
   1546  *****************************************************************************/
   1547 
   1548 ACPI_STATUS
   1549 DtCompileIvrs (
   1550     void                    **List)
   1551 {
   1552     ACPI_STATUS             Status;
   1553     DT_SUBTABLE             *Subtable;
   1554     DT_SUBTABLE             *ParentTable;
   1555     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1556     DT_FIELD                *SubtableStart;
   1557     ACPI_DMTABLE_INFO       *InfoTable;
   1558     ACPI_IVRS_HEADER        *IvrsHeader;
   1559     UINT8                   EntryType;
   1560 
   1561 
   1562     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
   1563         &Subtable, TRUE);
   1564     if (ACPI_FAILURE (Status))
   1565     {
   1566         return (Status);
   1567     }
   1568 
   1569     ParentTable = DtPeekSubtable ();
   1570     DtInsertSubtable (ParentTable, Subtable);
   1571 
   1572     while (*PFieldList)
   1573     {
   1574         SubtableStart = *PFieldList;
   1575         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr,
   1576             &Subtable, TRUE);
   1577         if (ACPI_FAILURE (Status))
   1578         {
   1579             return (Status);
   1580         }
   1581 
   1582         ParentTable = DtPeekSubtable ();
   1583         DtInsertSubtable (ParentTable, Subtable);
   1584         DtPushSubtable (Subtable);
   1585 
   1586         IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer);
   1587 
   1588         switch (IvrsHeader->Type)
   1589         {
   1590         case ACPI_IVRS_TYPE_HARDWARE:
   1591 
   1592             InfoTable = AcpiDmTableInfoIvrs0;
   1593             break;
   1594 
   1595         case ACPI_IVRS_TYPE_MEMORY1:
   1596         case ACPI_IVRS_TYPE_MEMORY2:
   1597         case ACPI_IVRS_TYPE_MEMORY3:
   1598 
   1599             InfoTable = AcpiDmTableInfoIvrs1;
   1600             break;
   1601 
   1602         default:
   1603 
   1604             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS");
   1605             return (AE_ERROR);
   1606         }
   1607 
   1608         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
   1609         if (ACPI_FAILURE (Status))
   1610         {
   1611             return (Status);
   1612         }
   1613 
   1614         ParentTable = DtPeekSubtable ();
   1615         DtInsertSubtable (ParentTable, Subtable);
   1616 
   1617         if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE)
   1618         {
   1619             while (*PFieldList &&
   1620                 !strcmp ((*PFieldList)->Name, "Entry Type"))
   1621             {
   1622                 SubtableStart = *PFieldList;
   1623                 DtCompileInteger (&EntryType, *PFieldList, 1, 0);
   1624 
   1625                 switch (EntryType)
   1626                 {
   1627                 /* 4-byte device entries */
   1628 
   1629                 case ACPI_IVRS_TYPE_PAD4:
   1630                 case ACPI_IVRS_TYPE_ALL:
   1631                 case ACPI_IVRS_TYPE_SELECT:
   1632                 case ACPI_IVRS_TYPE_START:
   1633                 case ACPI_IVRS_TYPE_END:
   1634 
   1635                     InfoTable = AcpiDmTableInfoIvrs4;
   1636                     break;
   1637 
   1638                 /* 8-byte entries, type A */
   1639 
   1640                 case ACPI_IVRS_TYPE_ALIAS_SELECT:
   1641                 case ACPI_IVRS_TYPE_ALIAS_START:
   1642 
   1643                     InfoTable = AcpiDmTableInfoIvrs8a;
   1644                     break;
   1645 
   1646                 /* 8-byte entries, type B */
   1647 
   1648                 case ACPI_IVRS_TYPE_PAD8:
   1649                 case ACPI_IVRS_TYPE_EXT_SELECT:
   1650                 case ACPI_IVRS_TYPE_EXT_START:
   1651 
   1652                     InfoTable = AcpiDmTableInfoIvrs8b;
   1653                     break;
   1654 
   1655                 /* 8-byte entries, type C */
   1656 
   1657                 case ACPI_IVRS_TYPE_SPECIAL:
   1658 
   1659                     InfoTable = AcpiDmTableInfoIvrs8c;
   1660                     break;
   1661 
   1662                 default:
   1663 
   1664                     DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
   1665                         "IVRS Device Entry");
   1666                     return (AE_ERROR);
   1667                 }
   1668 
   1669                 Status = DtCompileTable (PFieldList, InfoTable,
   1670                     &Subtable, TRUE);
   1671                 if (ACPI_FAILURE (Status))
   1672                 {
   1673                     return (Status);
   1674                 }
   1675 
   1676                 DtInsertSubtable (ParentTable, Subtable);
   1677             }
   1678         }
   1679 
   1680         DtPopSubtable ();
   1681     }
   1682 
   1683     return (AE_OK);
   1684 }
   1685