| /****************************************************************************** |
| * |
| * Module Name: dttable1.c - handling for specific ACPI tables |
| * |
| *****************************************************************************/ |
| |
| /* |
| * Copyright (C) 2000 - 2023, Intel Corp. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions, and the following disclaimer, |
| * without modification. |
| * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
| * substantially similar to the "NO WARRANTY" disclaimer below |
| * ("Disclaimer") and any redistribution must be conditioned upon |
| * including a substantially similar Disclaimer requirement for further |
| * binary redistribution. |
| * 3. Neither the names of the above-listed copyright holders nor the names |
| * of any contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * Alternatively, this software may be distributed under the terms of the |
| * GNU General Public License ("GPL") version 2 as published by the Free |
| * Software Foundation. |
| * |
| * NO WARRANTY |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGES. |
| */ |
| |
| /* Compile all complex data tables, signatures starting with A-I */ |
| |
| #include "aslcompiler.h" |
| |
| #define _COMPONENT DT_COMPILER |
| ACPI_MODULE_NAME ("dttable1") |
| |
| |
| static ACPI_DMTABLE_INFO TableInfoAsfAddress[] = |
| { |
| {ACPI_DMT_BUFFER, 0, "Addresses", 0}, |
| {ACPI_DMT_EXIT, 0, NULL, 0} |
| }; |
| |
| static ACPI_DMTABLE_INFO TableInfoDmarPciPath[] = |
| { |
| {ACPI_DMT_PCI_PATH, 0, "PCI Path", 0}, |
| {ACPI_DMT_EXIT, 0, NULL, 0} |
| }; |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileAest |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile AEST. |
| * |
| * NOTE: Assumes the following table structure: |
| * For all AEST Error Nodes: |
| * 1) An AEST Error Node, followed immediately by: |
| * 2) Any node-specific data |
| * 3) An Interface Structure (one) |
| * 4) A list (array) of Interrupt Structures, the count as specified |
| * in the NodeInterruptCount field of the Error Node header. |
| * |
| * AEST - ARM Error Source table. Conforms to: |
| * ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document Sep 2020 |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileAest ( |
| void **List) |
| { |
| ACPI_AEST_HEADER *ErrorNodeHeader; |
| ACPI_AEST_PROCESSOR *AestProcessor; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| ACPI_DMTABLE_INFO *InfoTable; |
| ACPI_STATUS Status; |
| UINT32 i; |
| UINT32 Offset; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| |
| |
| while (*PFieldList) |
| { |
| /* Compile the common error node header */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* Everything past the error node header will be a subtable */ |
| |
| DtPushSubtable (Subtable); |
| |
| /* |
| * Compile the node-specific structure (Based on the error |
| * node header Type field) |
| */ |
| ErrorNodeHeader = ACPI_CAST_PTR (ACPI_AEST_HEADER, Subtable->Buffer); |
| |
| /* Point past the common error node header */ |
| |
| Offset = sizeof (ACPI_AEST_HEADER); |
| ErrorNodeHeader->NodeSpecificOffset = Offset; |
| |
| /* Decode the error node type */ |
| |
| switch (ErrorNodeHeader->Type) |
| { |
| case ACPI_AEST_PROCESSOR_ERROR_NODE: |
| |
| InfoTable = AcpiDmTableInfoAestProcError; |
| break; |
| |
| case ACPI_AEST_MEMORY_ERROR_NODE: |
| |
| InfoTable = AcpiDmTableInfoAestMemError; |
| break; |
| |
| case ACPI_AEST_SMMU_ERROR_NODE: |
| |
| InfoTable = AcpiDmTableInfoAestSmmuError; |
| break; |
| |
| case ACPI_AEST_VENDOR_ERROR_NODE: |
| |
| InfoTable = AcpiDmTableInfoAestVendorError; |
| break; |
| |
| case ACPI_AEST_GIC_ERROR_NODE: |
| |
| InfoTable = AcpiDmTableInfoAestGicError; |
| break; |
| |
| /* Error case below */ |
| default: |
| AcpiOsPrintf ("Unknown AEST Subtable Type: %X\n", |
| ErrorNodeHeader->Type); |
| return (AE_ERROR); |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Point past the node-specific structure */ |
| |
| Offset += Subtable->Length; |
| ErrorNodeHeader->NodeInterfaceOffset = Offset; |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* Compile any additional node-specific substructures */ |
| |
| if (ErrorNodeHeader->Type == ACPI_AEST_PROCESSOR_ERROR_NODE) |
| { |
| /* |
| * Special handling for PROCESSOR_ERROR_NODE subtables |
| * (to handle the Resource Substructure via the ResourceType |
| * field). |
| */ |
| AestProcessor = ACPI_CAST_PTR (ACPI_AEST_PROCESSOR, |
| Subtable->Buffer); |
| |
| switch (AestProcessor->ResourceType) |
| { |
| case ACPI_AEST_CACHE_RESOURCE: |
| |
| InfoTable = AcpiDmTableInfoAestCacheRsrc; |
| break; |
| |
| case ACPI_AEST_TLB_RESOURCE: |
| |
| InfoTable = AcpiDmTableInfoAestTlbRsrc; |
| break; |
| |
| case ACPI_AEST_GENERIC_RESOURCE: |
| |
| InfoTable = AcpiDmTableInfoAestGenRsrc; |
| AcpiOsPrintf ("Generic Resource Type (%X) is not supported at this time\n", |
| AestProcessor->ResourceType); |
| return (AE_ERROR); |
| |
| /* Error case below */ |
| default: |
| AcpiOsPrintf ("Unknown AEST Processor Resource Type: %X\n", |
| AestProcessor->ResourceType); |
| return (AE_ERROR); |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Point past the resource substructure subtable */ |
| |
| Offset += Subtable->Length; |
| ErrorNodeHeader->NodeInterfaceOffset = Offset; |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| |
| /* Compile the (required) node interface structure */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXface, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ErrorNodeHeader->NodeInterruptOffset = 0; |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* Compile each of the node interrupt structures */ |
| |
| if (ErrorNodeHeader->NodeInterruptCount) |
| { |
| /* Point to the first interrupt structure */ |
| |
| Offset += Subtable->Length; |
| ErrorNodeHeader->NodeInterruptOffset = Offset; |
| } |
| |
| /* Compile each of the interrupt structures */ |
| |
| for (i = 0; i < ErrorNodeHeader->NodeInterruptCount; i++) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXrupt, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| |
| /* Prepare for the next AEST Error node */ |
| |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileApmt |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile APMT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileApmt ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| ACPI_TABLE_HEADER *Header; |
| ACPI_APMT_NODE *ApmtNode; |
| ACPI_APMT_NODE *PeerApmtNode; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *PeerSubtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD**)List; |
| DT_FIELD *SubtableStart; |
| UINT32 CurLength; |
| char MsgBuffer[64] = ""; |
| |
| ParentTable = DtPeekSubtable(); |
| |
| Header = ACPI_CAST_PTR(ACPI_TABLE_HEADER, ParentTable->Buffer); |
| |
| CurLength = sizeof(ACPI_TABLE_HEADER); |
| |
| /* Walk the parse tree */ |
| |
| while (*PFieldList) |
| { |
| /* APMT Node Subtable */ |
| |
| SubtableStart = *PFieldList; |
| |
| Status = DtCompileTable(PFieldList, AcpiDmTableInfoApmtNode, &Subtable); |
| |
| if (ACPI_FAILURE(Status)) |
| { |
| return (Status); |
| } |
| |
| ApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, Subtable->Buffer); |
| |
| if (ApmtNode->Length != sizeof(ACPI_APMT_NODE)) |
| { |
| DtFatal(ASL_MSG_INVALID_LENGTH, SubtableStart, "APMT"); |
| return (AE_ERROR); |
| } |
| |
| if (ApmtNode->Type >= ACPI_APMT_NODE_TYPE_COUNT) |
| { |
| snprintf(MsgBuffer, 64, "Node Type : 0x%X", ApmtNode->Type); |
| DtFatal(ASL_MSG_INVALID_TYPE, SubtableStart, MsgBuffer); |
| return (AE_ERROR); |
| } |
| |
| PeerSubtable = DtGetNextSubtable(ParentTable, NULL); |
| |
| /* Validate the node id needs to be unique. */ |
| while(PeerSubtable) |
| { |
| PeerApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, PeerSubtable->Buffer); |
| if (PeerApmtNode->Id == ApmtNode->Id) |
| { |
| snprintf(MsgBuffer, 64, "Node Id : 0x%X existed", ApmtNode->Id); |
| DtFatal(ASL_MSG_DUPLICATE_ITEM, SubtableStart, MsgBuffer); |
| return (AE_ERROR); |
| } |
| |
| PeerSubtable = DtGetNextSubtable(ParentTable, PeerSubtable); |
| } |
| |
| CurLength += ApmtNode->Length; |
| |
| DtInsertSubtable(ParentTable, Subtable); |
| } |
| |
| if (Header->Length != CurLength) |
| { |
| snprintf(MsgBuffer, 64, " - APMT Length : %u (expected: %u)", |
| Header->Length, CurLength); |
| DtFatal(ASL_MSG_INVALID_LENGTH, NULL, MsgBuffer); |
| return (AE_ERROR); |
| } |
| |
| return (AE_OK); |
| } |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileAsf |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile ASF!. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileAsf ( |
| void **List) |
| { |
| ACPI_ASF_INFO *AsfTable; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| ACPI_DMTABLE_INFO *InfoTable; |
| ACPI_DMTABLE_INFO *DataInfoTable = NULL; |
| UINT32 DataCount = 0; |
| ACPI_STATUS Status; |
| UINT32 i; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| |
| |
| while (*PFieldList) |
| { |
| SubtableStart = *PFieldList; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer); |
| |
| switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ |
| { |
| case ACPI_ASF_TYPE_INFO: |
| |
| InfoTable = AcpiDmTableInfoAsf0; |
| break; |
| |
| case ACPI_ASF_TYPE_ALERT: |
| |
| InfoTable = AcpiDmTableInfoAsf1; |
| break; |
| |
| case ACPI_ASF_TYPE_CONTROL: |
| |
| InfoTable = AcpiDmTableInfoAsf2; |
| break; |
| |
| case ACPI_ASF_TYPE_BOOT: |
| |
| InfoTable = AcpiDmTableInfoAsf3; |
| break; |
| |
| case ACPI_ASF_TYPE_ADDRESS: |
| |
| InfoTable = AcpiDmTableInfoAsf4; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); |
| return (AE_ERROR); |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */ |
| { |
| case ACPI_ASF_TYPE_INFO: |
| |
| DataInfoTable = NULL; |
| break; |
| |
| case ACPI_ASF_TYPE_ALERT: |
| |
| DataInfoTable = AcpiDmTableInfoAsf1a; |
| DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT, |
| ACPI_SUB_PTR (UINT8, Subtable->Buffer, |
| sizeof (ACPI_ASF_HEADER)))->Alerts; |
| break; |
| |
| case ACPI_ASF_TYPE_CONTROL: |
| |
| DataInfoTable = AcpiDmTableInfoAsf2a; |
| DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE, |
| ACPI_SUB_PTR (UINT8, Subtable->Buffer, |
| sizeof (ACPI_ASF_HEADER)))->Controls; |
| break; |
| |
| case ACPI_ASF_TYPE_BOOT: |
| |
| DataInfoTable = NULL; |
| break; |
| |
| case ACPI_ASF_TYPE_ADDRESS: |
| |
| DataInfoTable = TableInfoAsfAddress; |
| DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS, |
| ACPI_SUB_PTR (UINT8, Subtable->Buffer, |
| sizeof (ACPI_ASF_HEADER)))->Devices; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!"); |
| return (AE_ERROR); |
| } |
| |
| if (DataInfoTable) |
| { |
| switch (AsfTable->Header.Type & 0x7F) |
| { |
| case ACPI_ASF_TYPE_ADDRESS: |
| |
| while (DataCount > 0) |
| { |
| Status = DtCompileTable (PFieldList, DataInfoTable, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| DataCount = DataCount - Subtable->Length; |
| } |
| break; |
| |
| default: |
| |
| for (i = 0; i < DataCount; i++) |
| { |
| Status = DtCompileTable (PFieldList, DataInfoTable, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| break; |
| } |
| } |
| |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileAspt |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile ASPT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileAspt ( |
| void **List) |
| { |
| ACPI_ASPT_HEADER *AsptTable; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| ACPI_DMTABLE_INFO *InfoTable; |
| ACPI_STATUS Status; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoAspt, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| while (*PFieldList) |
| { |
| SubtableStart = *PFieldList; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsptHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| AsptTable = ACPI_CAST_PTR (ACPI_ASPT_HEADER, Subtable->Buffer); |
| |
| switch (AsptTable->Type) /* Mask off top bit */ |
| { |
| case ACPI_ASPT_TYPE_GLOBAL_REGS: |
| |
| InfoTable = AcpiDmTableInfoAspt0; |
| break; |
| |
| case ACPI_ASPT_TYPE_SEV_MBOX_REGS: |
| |
| InfoTable = AcpiDmTableInfoAspt1; |
| break; |
| |
| case ACPI_ASPT_TYPE_ACPI_MBOX_REGS: |
| |
| InfoTable = AcpiDmTableInfoAspt2; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASPT"); |
| return (AE_ERROR); |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileCdat |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile CDAT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileCdat ( |
| void **List) |
| { |
| ACPI_STATUS Status = AE_OK; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| ACPI_CDAT_HEADER *CdatHeader; |
| ACPI_DMTABLE_INFO *InfoTable = NULL; |
| DT_FIELD *SubtableStart; |
| |
| |
| /* Walk the parse tree. |
| * |
| * Note: Main table consists of only the CDAT table header |
| * (This is not the standard ACPI table header, however)-- |
| * Followed by some number of subtables. |
| */ |
| while (*PFieldList) |
| { |
| SubtableStart = *PFieldList; |
| |
| /* Compile the expected CDAT Subtable header */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatHeader, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| CdatHeader = ACPI_CAST_PTR (ACPI_CDAT_HEADER, Subtable->Buffer); |
| |
| /* Decode the subtable by type */ |
| |
| switch (CdatHeader->Type) |
| { |
| case ACPI_CDAT_TYPE_DSMAS: |
| InfoTable = AcpiDmTableInfoCdat0; |
| break; |
| |
| case ACPI_CDAT_TYPE_DSLBIS: |
| InfoTable = AcpiDmTableInfoCdat1; |
| break; |
| |
| case ACPI_CDAT_TYPE_DSMSCIS: |
| InfoTable = AcpiDmTableInfoCdat2; |
| break; |
| |
| case ACPI_CDAT_TYPE_DSIS: |
| InfoTable = AcpiDmTableInfoCdat3; |
| break; |
| |
| case ACPI_CDAT_TYPE_DSEMTS: |
| InfoTable = AcpiDmTableInfoCdat4; |
| break; |
| |
| case ACPI_CDAT_TYPE_SSLBIS: |
| InfoTable = AcpiDmTableInfoCdat5; |
| break; |
| |
| default: |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CDAT"); |
| } |
| |
| /* Compile the CDAT subtable */ |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| switch (CdatHeader->Type) |
| { |
| /* Multiple entries supported for this type */ |
| |
| case ACPI_CDAT_TYPE_SSLBIS: |
| |
| /* |
| * Check for multiple SSLBEs |
| */ |
| while (*PFieldList && !AcpiUtStricmp ((*PFieldList)->Name, "Port X ID")) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatEntries, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| /* Pop off the CDAT Subtable header subtree */ |
| |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileCedt |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile CEDT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileCedt ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| ACPI_CEDT_HEADER *CedtHeader; |
| DT_FIELD *SubtableStart; |
| |
| |
| /* Walk the parse tree */ |
| |
| while (*PFieldList) |
| { |
| /* if CFMWS and has more than one target, then set to zero later */ |
| |
| int InsertFlag = 1; |
| SubtableStart = *PFieldList; |
| |
| /* CEDT Header */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer); |
| |
| switch (CedtHeader->Type) |
| { |
| case ACPI_CEDT_TYPE_CHBS: |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| break; |
| case ACPI_CEDT_TYPE_CFMWS: { |
| unsigned char *dump; |
| unsigned int idx, offset, max = 0; |
| |
| /* Compile table with first "Interleave target" */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Look in buffer for the number of targets */ |
| offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CFMWS, InterleaveWays); |
| dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt1 */ |
| max = 0x01 << dump[offset]; /* 2^max, so 0=1, 1=2, 2=4, 3=8. 8 is MAX */ |
| if (max > 8) max=1; /* Error in encoding Interleaving Ways. */ |
| if (max == 1) /* if only one target, then break here. */ |
| break; /* break if only one target. */ |
| |
| /* We need to add more interleave targets, so write the current Subtable. */ |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt1 table so we can put in */ |
| DtPushSubtable (Subtable); /* the targets > the first. */ |
| |
| /* Now, find out all interleave targets beyond the first. */ |
| |
| for (idx = 1; idx < max; idx++) { |
| ParentTable = DtPeekSubtable (); |
| |
| if (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1_te, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (Subtable) |
| { |
| DtInsertSubtable (ParentTable, Subtable); /* got a target, so insert table. */ |
| InsertFlag = 0; |
| } |
| } |
| } |
| |
| DtPopSubtable (); |
| ParentTable = DtPeekSubtable (); |
| break; |
| } |
| |
| default: |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT"); |
| return (AE_ERROR); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| if (InsertFlag == 1) { |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileCpep |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile CPEP. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileCpep ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| |
| |
| Status = DtCompileTwoSubtables (List, |
| AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0); |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileCsrt |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile CSRT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileCsrt ( |
| void **List) |
| { |
| ACPI_STATUS Status = AE_OK; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| UINT32 DescriptorCount; |
| UINT32 GroupLength; |
| |
| |
| /* Subtables (Resource Groups) */ |
| |
| ParentTable = DtPeekSubtable (); |
| while (*PFieldList) |
| { |
| /* Resource group subtable */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Compute the number of resource descriptors */ |
| |
| GroupLength = |
| (ACPI_CAST_PTR (ACPI_CSRT_GROUP, |
| Subtable->Buffer))->Length - |
| (ACPI_CAST_PTR (ACPI_CSRT_GROUP, |
| Subtable->Buffer))->SharedInfoLength - |
| sizeof (ACPI_CSRT_GROUP); |
| |
| DescriptorCount = (GroupLength / |
| sizeof (ACPI_CSRT_DESCRIPTOR)); |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| ParentTable = DtPeekSubtable (); |
| |
| /* Shared info subtable (One per resource group) */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* Sub-Subtables (Resource Descriptors) */ |
| |
| while (*PFieldList && DescriptorCount) |
| { |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| DtPushSubtable (Subtable); |
| ParentTable = DtPeekSubtable (); |
| if (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (Subtable) |
| { |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| } |
| |
| DtPopSubtable (); |
| ParentTable = DtPeekSubtable (); |
| DescriptorCount--; |
| } |
| |
| DtPopSubtable (); |
| ParentTable = DtPeekSubtable (); |
| } |
| |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileDbg2 |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile DBG2. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileDbg2 ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| UINT32 SubtableCount; |
| ACPI_DBG2_HEADER *Dbg2Header; |
| ACPI_DBG2_DEVICE *DeviceInfo; |
| UINT16 CurrentOffset; |
| UINT32 i; |
| |
| |
| /* Main table */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* Main table fields */ |
| |
| Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer); |
| Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF ( |
| ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header); |
| |
| SubtableCount = Dbg2Header->InfoCount; |
| DtPushSubtable (Subtable); |
| |
| /* Process all Device Information subtables (Count = InfoCount) */ |
| |
| while (*PFieldList && SubtableCount) |
| { |
| /* Subtable: Debug Device Information */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer); |
| CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE); |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| ParentTable = DtPeekSubtable (); |
| |
| /* BaseAddressRegister GAS array (Required, size is RegisterCount) */ |
| |
| DeviceInfo->BaseAddressOffset = CurrentOffset; |
| for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS); |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| |
| /* AddressSize array (Required, size = RegisterCount) */ |
| |
| DeviceInfo->AddressSizeOffset = CurrentOffset; |
| for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| CurrentOffset += (UINT16) sizeof (UINT32); |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| |
| /* NamespaceString device identifier (Required, size = NamePathLength) */ |
| |
| DeviceInfo->NamepathOffset = CurrentOffset; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Update the device info header */ |
| |
| DeviceInfo->NamepathLength = (UINT16) Subtable->Length; |
| CurrentOffset += (UINT16) DeviceInfo->NamepathLength; |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* OemData - Variable-length data (Optional, size = OemDataLength) */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData, |
| &Subtable); |
| if (Status == AE_END_OF_TABLE) |
| { |
| /* optional field was not found and we're at the end of the file */ |
| |
| goto subtableDone; |
| } |
| else if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Update the device info header (zeros if no OEM data present) */ |
| |
| DeviceInfo->OemDataOffset = 0; |
| DeviceInfo->OemDataLength = 0; |
| |
| /* Optional subtable (OemData) */ |
| |
| if (Subtable && Subtable->Length) |
| { |
| DeviceInfo->OemDataOffset = CurrentOffset; |
| DeviceInfo->OemDataLength = (UINT16) Subtable->Length; |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| subtableDone: |
| SubtableCount--; |
| DtPopSubtable (); /* Get next Device Information subtable */ |
| } |
| |
| DtPopSubtable (); |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileDmar |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile DMAR. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileDmar ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| ACPI_DMTABLE_INFO *InfoTable; |
| ACPI_DMAR_HEADER *DmarHeader; |
| ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope; |
| UINT32 DeviceScopeLength; |
| UINT32 PciPathLength; |
| |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| while (*PFieldList) |
| { |
| /* DMAR Header */ |
| |
| SubtableStart = *PFieldList; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer); |
| |
| switch (DmarHeader->Type) |
| { |
| case ACPI_DMAR_TYPE_HARDWARE_UNIT: |
| |
| InfoTable = AcpiDmTableInfoDmar0; |
| break; |
| |
| case ACPI_DMAR_TYPE_RESERVED_MEMORY: |
| |
| InfoTable = AcpiDmTableInfoDmar1; |
| break; |
| |
| case ACPI_DMAR_TYPE_ROOT_ATS: |
| |
| InfoTable = AcpiDmTableInfoDmar2; |
| break; |
| |
| case ACPI_DMAR_TYPE_HARDWARE_AFFINITY: |
| |
| InfoTable = AcpiDmTableInfoDmar3; |
| break; |
| |
| case ACPI_DMAR_TYPE_NAMESPACE: |
| |
| InfoTable = AcpiDmTableInfoDmar4; |
| break; |
| |
| case ACPI_DMAR_TYPE_SATC: |
| |
| InfoTable = AcpiDmTableInfoDmar5; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR"); |
| return (AE_ERROR); |
| } |
| |
| /* DMAR Subtable */ |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* |
| * Optional Device Scope subtables |
| */ |
| if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) || |
| (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE)) |
| { |
| /* These types do not support device scopes */ |
| |
| DtPopSubtable (); |
| continue; |
| } |
| |
| DtPushSubtable (Subtable); |
| DeviceScopeLength = DmarHeader->Length - Subtable->Length - |
| ParentTable->Length; |
| while (DeviceScopeLength) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope, |
| &Subtable); |
| if (Status == AE_NOT_FOUND) |
| { |
| break; |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer); |
| |
| /* Optional PCI Paths */ |
| |
| PciPathLength = DmarDeviceScope->Length - Subtable->Length; |
| while (PciPathLength) |
| { |
| Status = DtCompileTable (PFieldList, TableInfoDmarPciPath, |
| &Subtable); |
| if (Status == AE_NOT_FOUND) |
| { |
| DtPopSubtable (); |
| break; |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| PciPathLength -= Subtable->Length; |
| } |
| |
| DtPopSubtable (); |
| DeviceScopeLength -= DmarDeviceScope->Length; |
| } |
| |
| DtPopSubtable (); |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileDrtm |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile DRTM. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileDrtm ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| UINT32 Count; |
| /* ACPI_TABLE_DRTM *Drtm; */ |
| ACPI_DRTM_VTABLE_LIST *DrtmVtl; |
| ACPI_DRTM_RESOURCE_LIST *DrtmRl; |
| /* ACPI_DRTM_DPS_ID *DrtmDps; */ |
| |
| |
| ParentTable = DtPeekSubtable (); |
| |
| /* Compile DRTM header */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* |
| * Using ACPI_SUB_PTR, We needn't define a separate structure. Care |
| * should be taken to avoid accessing ACPI_TABLE_HADER fields. |
| */ |
| #if 0 |
| Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM, |
| Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); |
| #endif |
| /* Compile VTL */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer); |
| |
| DtPushSubtable (Subtable); |
| ParentTable = DtPeekSubtable (); |
| Count = 0; |
| |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (!Subtable) |
| { |
| break; |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| Count++; |
| } |
| |
| DrtmVtl->ValidatedTableCount = Count; |
| DtPopSubtable (); |
| ParentTable = DtPeekSubtable (); |
| |
| /* Compile RL */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer); |
| |
| DtPushSubtable (Subtable); |
| ParentTable = DtPeekSubtable (); |
| Count = 0; |
| |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (!Subtable) |
| { |
| break; |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| Count++; |
| } |
| |
| DrtmRl->ResourceCount = Count; |
| DtPopSubtable (); |
| ParentTable = DtPeekSubtable (); |
| |
| /* Compile DPS */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/ |
| |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileEinj |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile EINJ. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileEinj ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| |
| |
| Status = DtCompileTwoSubtables (List, |
| AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0); |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileErst |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile ERST. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileErst ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| |
| |
| Status = DtCompileTwoSubtables (List, |
| AcpiDmTableInfoErst, AcpiDmTableInfoEinj0); |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileGtdt |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile GTDT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileGtdt ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| ACPI_SUBTABLE_HEADER *GtdtHeader; |
| ACPI_DMTABLE_INFO *InfoTable; |
| UINT32 GtCount; |
| ACPI_TABLE_HEADER *Header; |
| |
| |
| ParentTable = DtPeekSubtable (); |
| |
| Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); |
| |
| /* Compile the main table */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* GTDT revision 3 later contains 2 extra fields before subtables */ |
| |
| if (Header->Revision > 2) |
| { |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| Status = DtCompileTable (PFieldList, |
| AcpiDmTableInfoGtdtEl2, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| while (*PFieldList) |
| { |
| SubtableStart = *PFieldList; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer); |
| |
| switch (GtdtHeader->Type) |
| { |
| case ACPI_GTDT_TYPE_TIMER_BLOCK: |
| |
| InfoTable = AcpiDmTableInfoGtdt0; |
| break; |
| |
| case ACPI_GTDT_TYPE_WATCHDOG: |
| |
| InfoTable = AcpiDmTableInfoGtdt1; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT"); |
| return (AE_ERROR); |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* |
| * Additional GT block subtable data |
| */ |
| |
| switch (GtdtHeader->Type) |
| { |
| case ACPI_GTDT_TYPE_TIMER_BLOCK: |
| |
| DtPushSubtable (Subtable); |
| ParentTable = DtPeekSubtable (); |
| |
| GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK, |
| Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount; |
| |
| while (GtCount) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| GtCount--; |
| } |
| |
| DtPopSubtable (); |
| break; |
| |
| default: |
| |
| break; |
| } |
| |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileFpdt |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile FPDT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileFpdt ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| ACPI_FPDT_HEADER *FpdtHeader; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| ACPI_DMTABLE_INFO *InfoTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| |
| |
| while (*PFieldList) |
| { |
| SubtableStart = *PFieldList; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer); |
| |
| switch (FpdtHeader->Type) |
| { |
| case ACPI_FPDT_TYPE_BOOT: |
| |
| InfoTable = AcpiDmTableInfoFpdt0; |
| break; |
| |
| case ACPI_FPDT_TYPE_S3PERF: |
| |
| InfoTable = AcpiDmTableInfoFpdt1; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT"); |
| return (AE_ERROR); |
| break; |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPopSubtable (); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileHest |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile HEST. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileHest ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| ACPI_DMTABLE_INFO *InfoTable; |
| UINT16 Type; |
| UINT32 BankCount; |
| |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| while (*PFieldList) |
| { |
| /* Get subtable type */ |
| |
| SubtableStart = *PFieldList; |
| DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0); |
| |
| switch (Type) |
| { |
| case ACPI_HEST_TYPE_IA32_CHECK: |
| |
| InfoTable = AcpiDmTableInfoHest0; |
| break; |
| |
| case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: |
| |
| InfoTable = AcpiDmTableInfoHest1; |
| break; |
| |
| case ACPI_HEST_TYPE_IA32_NMI: |
| |
| InfoTable = AcpiDmTableInfoHest2; |
| break; |
| |
| case ACPI_HEST_TYPE_AER_ROOT_PORT: |
| |
| InfoTable = AcpiDmTableInfoHest6; |
| break; |
| |
| case ACPI_HEST_TYPE_AER_ENDPOINT: |
| |
| InfoTable = AcpiDmTableInfoHest7; |
| break; |
| |
| case ACPI_HEST_TYPE_AER_BRIDGE: |
| |
| InfoTable = AcpiDmTableInfoHest8; |
| break; |
| |
| case ACPI_HEST_TYPE_GENERIC_ERROR: |
| |
| InfoTable = AcpiDmTableInfoHest9; |
| break; |
| |
| case ACPI_HEST_TYPE_GENERIC_ERROR_V2: |
| |
| InfoTable = AcpiDmTableInfoHest10; |
| break; |
| |
| case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: |
| |
| InfoTable = AcpiDmTableInfoHest11; |
| break; |
| |
| default: |
| |
| /* Cannot continue on unknown type */ |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST"); |
| return (AE_ERROR); |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* |
| * Additional subtable data - IA32 Error Bank(s) |
| */ |
| BankCount = 0; |
| switch (Type) |
| { |
| case ACPI_HEST_TYPE_IA32_CHECK: |
| |
| BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK, |
| Subtable->Buffer))->NumHardwareBanks; |
| break; |
| |
| case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: |
| |
| BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED, |
| Subtable->Buffer))->NumHardwareBanks; |
| break; |
| |
| case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: |
| |
| BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK, |
| Subtable->Buffer))->NumHardwareBanks; |
| break; |
| |
| default: |
| |
| break; |
| } |
| |
| while (BankCount) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| BankCount--; |
| } |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileHmat |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile HMAT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileHmat ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| DT_FIELD *EntryStart; |
| ACPI_HMAT_STRUCTURE *HmatStruct; |
| ACPI_HMAT_LOCALITY *HmatLocality; |
| ACPI_HMAT_CACHE *HmatCache; |
| ACPI_DMTABLE_INFO *InfoTable; |
| UINT32 IntPDNumber; |
| UINT32 TgtPDNumber; |
| UINT64 EntryNumber; |
| UINT16 SMBIOSHandleNumber; |
| |
| |
| ParentTable = DtPeekSubtable (); |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| while (*PFieldList) |
| { |
| /* Compile HMAT structure header */ |
| |
| SubtableStart = *PFieldList; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer); |
| HmatStruct->Length = Subtable->Length; |
| |
| /* Compile HMAT structure body */ |
| |
| switch (HmatStruct->Type) |
| { |
| case ACPI_HMAT_TYPE_ADDRESS_RANGE: |
| |
| InfoTable = AcpiDmTableInfoHmat0; |
| break; |
| |
| case ACPI_HMAT_TYPE_LOCALITY: |
| |
| InfoTable = AcpiDmTableInfoHmat1; |
| break; |
| |
| case ACPI_HMAT_TYPE_CACHE: |
| |
| InfoTable = AcpiDmTableInfoHmat2; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT"); |
| return (AE_ERROR); |
| } |
| |
| Status = DtCompileTable (PFieldList, InfoTable, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| HmatStruct->Length += Subtable->Length; |
| |
| /* Compile HMAT structure additional */ |
| |
| switch (HmatStruct->Type) |
| { |
| case ACPI_HMAT_TYPE_LOCALITY: |
| |
| HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY, |
| Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); |
| |
| /* Compile initiator proximity domain list */ |
| |
| IntPDNumber = 0; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, |
| AcpiDmTableInfoHmat1a, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (!Subtable) |
| { |
| break; |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| HmatStruct->Length += Subtable->Length; |
| IntPDNumber++; |
| } |
| HmatLocality->NumberOfInitiatorPDs = IntPDNumber; |
| |
| /* Compile target proximity domain list */ |
| |
| TgtPDNumber = 0; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, |
| AcpiDmTableInfoHmat1b, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (!Subtable) |
| { |
| break; |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| HmatStruct->Length += Subtable->Length; |
| TgtPDNumber++; |
| } |
| HmatLocality->NumberOfTargetPDs = TgtPDNumber; |
| |
| /* Save start of the entries for reporting errors */ |
| |
| EntryStart = *PFieldList; |
| |
| /* Compile latency/bandwidth entries */ |
| |
| EntryNumber = 0; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, |
| AcpiDmTableInfoHmat1c, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (!Subtable) |
| { |
| break; |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| HmatStruct->Length += Subtable->Length; |
| EntryNumber++; |
| } |
| |
| /* Validate number of entries */ |
| |
| if (EntryNumber != |
| ((UINT64)IntPDNumber * (UINT64)TgtPDNumber)) |
| { |
| DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT"); |
| return (AE_ERROR); |
| } |
| break; |
| |
| case ACPI_HMAT_TYPE_CACHE: |
| |
| /* Compile SMBIOS handles */ |
| |
| HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE, |
| Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE)); |
| SMBIOSHandleNumber = 0; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, |
| AcpiDmTableInfoHmat2a, &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (!Subtable) |
| { |
| break; |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| HmatStruct->Length += Subtable->Length; |
| SMBIOSHandleNumber++; |
| } |
| HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber; |
| break; |
| |
| default: |
| |
| break; |
| } |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileIort |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile IORT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileIort ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| ACPI_TABLE_HEADER *Table; |
| ACPI_TABLE_IORT *Iort; |
| ACPI_IORT_NODE *IortNode; |
| ACPI_IORT_ITS_GROUP *IortItsGroup; |
| ACPI_IORT_SMMU *IortSmmu; |
| ACPI_IORT_RMR *IortRmr; |
| UINT32 NodeNumber; |
| UINT32 NodeLength; |
| UINT32 IdMappingNumber; |
| UINT32 ItsNumber; |
| UINT32 ContextIrptNumber; |
| UINT32 PmuIrptNumber; |
| UINT32 PaddingLength; |
| UINT8 Revision; |
| UINT32 RmrCount; |
| |
| |
| ParentTable = DtPeekSubtable (); |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer); |
| Revision = Table->Revision; |
| |
| /* IORT Revisions E, E.a & E.c have known issues and are not supported */ |
| |
| if (Revision == 1 || Revision == 2 || Revision == 4) |
| { |
| DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision"); |
| return (AE_ERROR); |
| } |
| |
| /* |
| * Using ACPI_SUB_PTR, We needn't define a separate structure. Care |
| * should be taken to avoid accessing ACPI_TABLE_HEADER fields. |
| */ |
| Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT, |
| Subtable->Buffer, sizeof (ACPI_TABLE_HEADER)); |
| |
| /* |
| * OptionalPadding - Variable-length data |
| * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT)) |
| * Optionally allows the generic data types to be used for filling |
| * this field. |
| */ |
| Iort->NodeOffset = sizeof (ACPI_TABLE_IORT); |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (Subtable) |
| { |
| DtInsertSubtable (ParentTable, Subtable); |
| Iort->NodeOffset += Subtable->Length; |
| } |
| else |
| { |
| Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList), |
| AcpiDmTableInfoIortHdr[0].Name, &PaddingLength); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| Iort->NodeOffset += PaddingLength; |
| } |
| |
| NodeNumber = 0; |
| while (*PFieldList) |
| { |
| SubtableStart = *PFieldList; |
| if (Revision == 0) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr, |
| &Subtable); |
| } |
| else if (Revision >= 3) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3, |
| &Subtable); |
| } |
| |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer); |
| NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData); |
| |
| DtPushSubtable (Subtable); |
| ParentTable = DtPeekSubtable (); |
| |
| switch (IortNode->Type) |
| { |
| case ACPI_IORT_NODE_ITS_GROUP: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer); |
| NodeLength += Subtable->Length; |
| |
| ItsNumber = 0; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| if (!Subtable) |
| { |
| break; |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| ItsNumber++; |
| } |
| |
| IortItsGroup->ItsCount = ItsNumber; |
| break; |
| |
| case ACPI_IORT_NODE_NAMED_COMPONENT: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| |
| /* |
| * Padding - Variable-length data |
| * Optionally allows the offset of the ID mappings to be used |
| * for filling this field. |
| */ |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (Subtable) |
| { |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| } |
| else |
| { |
| if (NodeLength > IortNode->MappingOffset) |
| { |
| return (AE_BAD_DATA); |
| } |
| |
| if (NodeLength < IortNode->MappingOffset) |
| { |
| Status = DtCompilePadding ( |
| IortNode->MappingOffset - NodeLength, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength = IortNode->MappingOffset; |
| } |
| } |
| break; |
| |
| case ACPI_IORT_NODE_PCI_ROOT_COMPLEX: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| break; |
| |
| case ACPI_IORT_NODE_SMMU: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer); |
| NodeLength += Subtable->Length; |
| |
| /* Compile global interrupt array */ |
| |
| IortSmmu->GlobalInterruptOffset = NodeLength; |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| |
| /* Compile context interrupt array */ |
| |
| ContextIrptNumber = 0; |
| IortSmmu->ContextInterruptOffset = NodeLength; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (!Subtable) |
| { |
| break; |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| ContextIrptNumber++; |
| } |
| |
| IortSmmu->ContextInterruptCount = ContextIrptNumber; |
| |
| /* Compile PMU interrupt array */ |
| |
| PmuIrptNumber = 0; |
| IortSmmu->PmuInterruptOffset = NodeLength; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (!Subtable) |
| { |
| break; |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| PmuIrptNumber++; |
| } |
| |
| IortSmmu->PmuInterruptCount = PmuIrptNumber; |
| break; |
| |
| case ACPI_IORT_NODE_SMMU_V3: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| break; |
| |
| case ACPI_IORT_NODE_PMCG: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += Subtable->Length; |
| break; |
| |
| case ACPI_IORT_NODE_RMR: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer); |
| NodeLength += Subtable->Length; |
| |
| /* Compile RMR Descriptors */ |
| |
| RmrCount = 0; |
| IortRmr->RmrOffset = NodeLength; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (!Subtable) |
| { |
| break; |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += sizeof (ACPI_IORT_RMR_DESC); |
| RmrCount++; |
| } |
| |
| IortRmr->RmrCount = RmrCount; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT"); |
| return (AE_ERROR); |
| } |
| |
| /* Compile Array of ID mappings */ |
| |
| IortNode->MappingOffset = NodeLength; |
| IdMappingNumber = 0; |
| while (*PFieldList) |
| { |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (!Subtable) |
| { |
| break; |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| NodeLength += sizeof (ACPI_IORT_ID_MAPPING); |
| IdMappingNumber++; |
| } |
| |
| IortNode->MappingCount = IdMappingNumber; |
| if (!IdMappingNumber) |
| { |
| IortNode->MappingOffset = 0; |
| } |
| |
| /* |
| * Node length can be determined by DT_LENGTH option |
| * IortNode->Length = NodeLength; |
| */ |
| DtPopSubtable (); |
| ParentTable = DtPeekSubtable (); |
| NodeNumber++; |
| } |
| |
| Iort->NodeCount = NodeNumber; |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: DtCompileIvrs |
| * |
| * PARAMETERS: List - Current field list pointer |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Compile IVRS. Notes: |
| * The IVRS is essentially a flat table, with the following |
| * structure: |
| * <Main ACPI Table Header> |
| * <Main subtable - virtualization info> |
| * <IVHD> |
| * <Device Entries> |
| * ... |
| * <IVHD> |
| * <Device Entries> |
| * <IVMD> |
| * ... |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| DtCompileIvrs ( |
| void **List) |
| { |
| ACPI_STATUS Status; |
| DT_SUBTABLE *Subtable; |
| DT_SUBTABLE *ParentTable; |
| DT_SUBTABLE *MainSubtable; |
| DT_FIELD **PFieldList = (DT_FIELD **) List; |
| DT_FIELD *SubtableStart; |
| ACPI_DMTABLE_INFO *InfoTable = NULL; |
| UINT8 SubtableType; |
| UINT8 Temp64[16]; |
| UINT8 Temp8; |
| |
| |
| /* Main table */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| DtInsertSubtable (ParentTable, Subtable); |
| DtPushSubtable (Subtable); |
| |
| /* Save a pointer to the main subtable */ |
| |
| MainSubtable = Subtable; |
| |
| while (*PFieldList) |
| { |
| SubtableStart = *PFieldList; |
| |
| /* Compile the SubtableType integer */ |
| |
| DtCompileInteger (&SubtableType, *PFieldList, 1, 0); |
| |
| switch (SubtableType) |
| { |
| |
| /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */ |
| |
| case ACPI_IVRS_TYPE_HARDWARE1: |
| |
| InfoTable = AcpiDmTableInfoIvrsHware1; |
| break; |
| |
| /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */ |
| |
| case ACPI_IVRS_TYPE_HARDWARE2: |
| case ACPI_IVRS_TYPE_HARDWARE3: |
| |
| InfoTable = AcpiDmTableInfoIvrsHware23; |
| break; |
| |
| /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */ |
| |
| case ACPI_IVRS_TYPE_MEMORY1: |
| case ACPI_IVRS_TYPE_MEMORY2: |
| case ACPI_IVRS_TYPE_MEMORY3: |
| |
| InfoTable = AcpiDmTableInfoIvrsMemory; |
| break; |
| |
| /* 4-byte device entries */ |
| |
| case ACPI_IVRS_TYPE_PAD4: |
| case ACPI_IVRS_TYPE_ALL: |
| case ACPI_IVRS_TYPE_SELECT: |
| case ACPI_IVRS_TYPE_START: |
| case ACPI_IVRS_TYPE_END: |
| |
| InfoTable = AcpiDmTableInfoIvrs4; |
| break; |
| |
| /* 8-byte device entries, type A */ |
| |
| case ACPI_IVRS_TYPE_ALIAS_SELECT: |
| case ACPI_IVRS_TYPE_ALIAS_START: |
| |
| InfoTable = AcpiDmTableInfoIvrs8a; |
| break; |
| |
| /* 8-byte device entries, type B */ |
| |
| case ACPI_IVRS_TYPE_EXT_SELECT: |
| case ACPI_IVRS_TYPE_EXT_START: |
| |
| InfoTable = AcpiDmTableInfoIvrs8b; |
| break; |
| |
| /* 8-byte device entries, type C */ |
| |
| case ACPI_IVRS_TYPE_SPECIAL: |
| |
| InfoTable = AcpiDmTableInfoIvrs8c; |
| break; |
| |
| /* Variable device entries, type F0h */ |
| |
| case ACPI_IVRS_TYPE_HID: |
| |
| InfoTable = AcpiDmTableInfoIvrsHid; |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, |
| "IVRS Device Entry"); |
| return (AE_ERROR); |
| } |
| |
| /* Compile the InfoTable from above */ |
| |
| Status = DtCompileTable (PFieldList, InfoTable, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| ParentTable = DtPeekSubtable (); |
| if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 && |
| SubtableType != ACPI_IVRS_TYPE_HARDWARE2 && |
| SubtableType != ACPI_IVRS_TYPE_HARDWARE3 && |
| SubtableType != ACPI_IVRS_TYPE_HID && |
| SubtableType != ACPI_IVRS_TYPE_MEMORY1 && |
| SubtableType != ACPI_IVRS_TYPE_MEMORY2 && |
| SubtableType != ACPI_IVRS_TYPE_MEMORY3) |
| { |
| if (ParentTable) |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| |
| switch (SubtableType) |
| { |
| case ACPI_IVRS_TYPE_HARDWARE1: |
| case ACPI_IVRS_TYPE_HARDWARE2: |
| case ACPI_IVRS_TYPE_HARDWARE3: |
| case ACPI_IVRS_TYPE_MEMORY1: |
| case ACPI_IVRS_TYPE_MEMORY2: |
| case ACPI_IVRS_TYPE_MEMORY3: |
| |
| /* Insert these IVHDs/IVMDs at the root subtable */ |
| |
| DtInsertSubtable (MainSubtable, Subtable); |
| DtPushSubtable (Subtable); |
| break; |
| |
| case ACPI_IVRS_TYPE_HID: |
| |
| /* Special handling for the HID named device entry (0xF0) */ |
| |
| if (ParentTable) |
| { |
| DtInsertSubtable (ParentTable, Subtable); |
| } |
| |
| /* |
| * Process the HID value. First, get the HID value as a string. |
| */ |
| DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); |
| |
| /* |
| * Determine if the HID is an integer or a string. |
| * An integer is defined to be 32 bits, with the upper 32 bits |
| * set to zero. (from the ACPI Spec): "The HID can be a 32-bit |
| * integer or a character string. If an integer, the lower |
| * 4 bytes of the field contain the integer and the upper |
| * 4 bytes are padded with 0". |
| */ |
| if (UtIsIdInteger ((UINT8 *) &Temp64)) |
| { |
| /* Compile the HID value as an integer */ |
| |
| DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| else |
| { |
| /* Compile the HID value as a string */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* |
| * Process the CID value. First, get the CID value as a string. |
| */ |
| DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0); |
| |
| if (UtIsIdInteger ((UINT8 *) &Temp64)) |
| { |
| /* Compile the CID value as an integer */ |
| |
| DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0); |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| else |
| { |
| /* Compile the CID value as a string */ |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| |
| DtInsertSubtable (ParentTable, Subtable); |
| |
| /* |
| * Process the UID value. First, get and decode the "UID Format" field (Integer). |
| */ |
| if (!*PFieldList) |
| { |
| return (AE_OK); |
| } |
| |
| DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0); |
| |
| switch (Temp8) |
| { |
| case ACPI_IVRS_UID_NOT_PRESENT: |
| break; |
| |
| case ACPI_IVRS_UID_IS_INTEGER: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| break; |
| |
| case ACPI_IVRS_UID_IS_STRING: |
| |
| Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString, |
| &Subtable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| DtInsertSubtable (ParentTable, Subtable); |
| break; |
| |
| default: |
| |
| DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart, |
| "IVRS Device Entry"); |
| return (AE_ERROR); |
| } |
| |
| default: |
| |
| /* All other subtable types come through here */ |
| break; |
| } |
| } |
| |
| return (AE_OK); |
| } |