128c506b8Sjruoho /****************************************************************************** 228c506b8Sjruoho * 328c506b8Sjruoho * Module Name: aslresource - Resource template/descriptor utilities 428c506b8Sjruoho * 528c506b8Sjruoho *****************************************************************************/ 628c506b8Sjruoho 7124f4c82Sjruoho /* 8046a2985Schristos * Copyright (C) 2000 - 2023, Intel Corp. 928c506b8Sjruoho * All rights reserved. 1028c506b8Sjruoho * 11124f4c82Sjruoho * Redistribution and use in source and binary forms, with or without 12124f4c82Sjruoho * modification, are permitted provided that the following conditions 13124f4c82Sjruoho * are met: 14124f4c82Sjruoho * 1. Redistributions of source code must retain the above copyright 15124f4c82Sjruoho * notice, this list of conditions, and the following disclaimer, 16124f4c82Sjruoho * without modification. 17124f4c82Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18124f4c82Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below 19124f4c82Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon 20124f4c82Sjruoho * including a substantially similar Disclaimer requirement for further 21124f4c82Sjruoho * binary redistribution. 22124f4c82Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names 23124f4c82Sjruoho * of any contributors may be used to endorse or promote products derived 24124f4c82Sjruoho * from this software without specific prior written permission. 2528c506b8Sjruoho * 26124f4c82Sjruoho * Alternatively, this software may be distributed under the terms of the 27124f4c82Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free 28124f4c82Sjruoho * Software Foundation. 2928c506b8Sjruoho * 30124f4c82Sjruoho * NO WARRANTY 31124f4c82Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32124f4c82Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3346a330b4Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34124f4c82Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35124f4c82Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36124f4c82Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37124f4c82Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38124f4c82Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39124f4c82Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40124f4c82Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41124f4c82Sjruoho * POSSIBILITY OF SUCH DAMAGES. 42124f4c82Sjruoho */ 4328c506b8Sjruoho 4428c506b8Sjruoho #include "aslcompiler.h" 4528c506b8Sjruoho #include "aslcompiler.y.h" 4628c506b8Sjruoho #include "amlcode.h" 4728c506b8Sjruoho 4828c506b8Sjruoho 4928c506b8Sjruoho #define _COMPONENT ACPI_COMPILER 5028c506b8Sjruoho ACPI_MODULE_NAME ("aslresource") 5128c506b8Sjruoho 5228c506b8Sjruoho 5328c506b8Sjruoho /******************************************************************************* 5428c506b8Sjruoho * 5528c506b8Sjruoho * FUNCTION: RsSmallAddressCheck 5628c506b8Sjruoho * 5728c506b8Sjruoho * PARAMETERS: Minimum - Address Min value 5828c506b8Sjruoho * Maximum - Address Max value 5928c506b8Sjruoho * Length - Address range value 6028c506b8Sjruoho * Alignment - Address alignment value 6128c506b8Sjruoho * MinOp - Original Op for Address Min 6228c506b8Sjruoho * MaxOp - Original Op for Address Max 6328c506b8Sjruoho * LengthOp - Original Op for address range 6428c506b8Sjruoho * AlignOp - Original Op for address alignment. If 6528c506b8Sjruoho * NULL, means "zero value for alignment is 6628c506b8Sjruoho * OK, and means 64K alignment" (for 6728c506b8Sjruoho * Memory24 descriptor) 68124f4c82Sjruoho * Op - Parent Op for entire construct 6928c506b8Sjruoho * 7028c506b8Sjruoho * RETURN: None. Adds error messages to error log if necessary 7128c506b8Sjruoho * 7228c506b8Sjruoho * DESCRIPTION: Perform common value checks for "small" address descriptors. 7328c506b8Sjruoho * Currently: 7428c506b8Sjruoho * Io, Memory24, Memory32 7528c506b8Sjruoho * 7628c506b8Sjruoho ******************************************************************************/ 7728c506b8Sjruoho 7828c506b8Sjruoho void 7928c506b8Sjruoho RsSmallAddressCheck ( 8028c506b8Sjruoho UINT8 Type, 8128c506b8Sjruoho UINT32 Minimum, 8228c506b8Sjruoho UINT32 Maximum, 8328c506b8Sjruoho UINT32 Length, 8428c506b8Sjruoho UINT32 Alignment, 8528c506b8Sjruoho ACPI_PARSE_OBJECT *MinOp, 8628c506b8Sjruoho ACPI_PARSE_OBJECT *MaxOp, 8728c506b8Sjruoho ACPI_PARSE_OBJECT *LengthOp, 88124f4c82Sjruoho ACPI_PARSE_OBJECT *AlignOp, 89124f4c82Sjruoho ACPI_PARSE_OBJECT *Op) 9028c506b8Sjruoho { 9128c506b8Sjruoho 924c4e8184Schristos if (AslGbl_NoResourceChecking) 9328c506b8Sjruoho { 9428c506b8Sjruoho return; 9528c506b8Sjruoho } 9628c506b8Sjruoho 97124f4c82Sjruoho /* 98124f4c82Sjruoho * Check for a so-called "null descriptor". These are descriptors that are 99124f4c82Sjruoho * created with most fields set to zero. The intent is that the descriptor 100124f4c82Sjruoho * will be updated/completed at runtime via a BufferField. 101124f4c82Sjruoho * 102124f4c82Sjruoho * If the descriptor does NOT have a resource tag, it cannot be referenced 103124f4c82Sjruoho * by a BufferField and we will flag this as an error. Conversely, if 104124f4c82Sjruoho * the descriptor has a resource tag, we will assume that a BufferField 105124f4c82Sjruoho * will be used to dynamically update it, so no error. 106124f4c82Sjruoho * 107124f4c82Sjruoho * A possible enhancement to this check would be to verify that in fact 108124f4c82Sjruoho * a BufferField is created using the resource tag, and perhaps even 109124f4c82Sjruoho * verify that a Store is performed to the BufferField. 110124f4c82Sjruoho * 111124f4c82Sjruoho * Note: for these descriptors, Alignment is allowed to be zero 112124f4c82Sjruoho */ 113124f4c82Sjruoho if (!Minimum && !Maximum && !Length) 114124f4c82Sjruoho { 115124f4c82Sjruoho if (!Op->Asl.ExternalName) 116124f4c82Sjruoho { 117124f4c82Sjruoho /* No resource tag. Descriptor is fixed and is also illegal */ 118124f4c82Sjruoho 119124f4c82Sjruoho AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL); 120124f4c82Sjruoho } 121124f4c82Sjruoho 122124f4c82Sjruoho return; 123124f4c82Sjruoho } 124124f4c82Sjruoho 125460301d4Schristos /* 126460301d4Schristos * Range checks for Memory24 and Memory32. 127460301d4Schristos * IO descriptor has different definition of min/max, don't check. 128460301d4Schristos */ 12928c506b8Sjruoho if (Type != ACPI_RESOURCE_NAME_IO) 13028c506b8Sjruoho { 13128c506b8Sjruoho /* Basic checks on Min/Max/Length */ 13228c506b8Sjruoho 13328c506b8Sjruoho if (Minimum > Maximum) 13428c506b8Sjruoho { 13528c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); 13628c506b8Sjruoho } 13728c506b8Sjruoho else if (Length > (Maximum - Minimum + 1)) 13828c506b8Sjruoho { 13928c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); 14028c506b8Sjruoho } 141460301d4Schristos 142460301d4Schristos /* Special case for Memory24, min/max values are compressed */ 143460301d4Schristos 144460301d4Schristos if (Type == ACPI_RESOURCE_NAME_MEMORY24) 145460301d4Schristos { 146460301d4Schristos if (!Alignment) /* Alignment==0 means 64K alignment */ 147460301d4Schristos { 148460301d4Schristos Alignment = ACPI_UINT16_MAX + 1; 149460301d4Schristos } 150460301d4Schristos 151460301d4Schristos Minimum <<= 8; 152460301d4Schristos Maximum <<= 8; 153460301d4Schristos } 15428c506b8Sjruoho } 15528c506b8Sjruoho 15628c506b8Sjruoho /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */ 15728c506b8Sjruoho 15828c506b8Sjruoho if (!Alignment) 15928c506b8Sjruoho { 16028c506b8Sjruoho Alignment = 1; 16128c506b8Sjruoho } 16228c506b8Sjruoho 16328c506b8Sjruoho /* Addresses must be an exact multiple of the alignment value */ 16428c506b8Sjruoho 16528c506b8Sjruoho if (Minimum % Alignment) 16628c506b8Sjruoho { 16728c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); 16828c506b8Sjruoho } 16928c506b8Sjruoho if (Maximum % Alignment) 17028c506b8Sjruoho { 17128c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL); 17228c506b8Sjruoho } 17328c506b8Sjruoho } 17428c506b8Sjruoho 17528c506b8Sjruoho 17628c506b8Sjruoho /******************************************************************************* 17728c506b8Sjruoho * 17828c506b8Sjruoho * FUNCTION: RsLargeAddressCheck 17928c506b8Sjruoho * 18028c506b8Sjruoho * PARAMETERS: Minimum - Address Min value 18128c506b8Sjruoho * Maximum - Address Max value 18228c506b8Sjruoho * Length - Address range value 18328c506b8Sjruoho * Granularity - Address granularity value 18428c506b8Sjruoho * Flags - General flags for address descriptors: 18528c506b8Sjruoho * _MIF, _MAF, _DEC 18628c506b8Sjruoho * MinOp - Original Op for Address Min 18728c506b8Sjruoho * MaxOp - Original Op for Address Max 18828c506b8Sjruoho * LengthOp - Original Op for address range 18928c506b8Sjruoho * GranOp - Original Op for address granularity 190124f4c82Sjruoho * Op - Parent Op for entire construct 19128c506b8Sjruoho * 19228c506b8Sjruoho * RETURN: None. Adds error messages to error log if necessary 19328c506b8Sjruoho * 19428c506b8Sjruoho * DESCRIPTION: Perform common value checks for "large" address descriptors. 19528c506b8Sjruoho * Currently: 19628c506b8Sjruoho * WordIo, WordBusNumber, WordSpace 19728c506b8Sjruoho * DWordIo, DWordMemory, DWordSpace 19828c506b8Sjruoho * QWordIo, QWordMemory, QWordSpace 19928c506b8Sjruoho * ExtendedIo, ExtendedMemory, ExtendedSpace 20028c506b8Sjruoho * 20128c506b8Sjruoho * _MIF flag set means that the minimum address is fixed and is not relocatable 20228c506b8Sjruoho * _MAF flag set means that the maximum address is fixed and is not relocatable 20328c506b8Sjruoho * Length of zero means that the record size is variable 20428c506b8Sjruoho * 20528c506b8Sjruoho * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40 20628c506b8Sjruoho * of the ACPI 4.0a specification. Added 04/2010. 20728c506b8Sjruoho * 20828c506b8Sjruoho ******************************************************************************/ 20928c506b8Sjruoho 21028c506b8Sjruoho void 21128c506b8Sjruoho RsLargeAddressCheck ( 21228c506b8Sjruoho UINT64 Minimum, 21328c506b8Sjruoho UINT64 Maximum, 21428c506b8Sjruoho UINT64 Length, 21528c506b8Sjruoho UINT64 Granularity, 21628c506b8Sjruoho UINT8 Flags, 21728c506b8Sjruoho ACPI_PARSE_OBJECT *MinOp, 21828c506b8Sjruoho ACPI_PARSE_OBJECT *MaxOp, 21928c506b8Sjruoho ACPI_PARSE_OBJECT *LengthOp, 220124f4c82Sjruoho ACPI_PARSE_OBJECT *GranOp, 221124f4c82Sjruoho ACPI_PARSE_OBJECT *Op) 22228c506b8Sjruoho { 22328c506b8Sjruoho 2244c4e8184Schristos if (AslGbl_NoResourceChecking) 22528c506b8Sjruoho { 22628c506b8Sjruoho return; 22728c506b8Sjruoho } 22828c506b8Sjruoho 229124f4c82Sjruoho /* 230124f4c82Sjruoho * Check for a so-called "null descriptor". These are descriptors that are 231124f4c82Sjruoho * created with most fields set to zero. The intent is that the descriptor 232124f4c82Sjruoho * will be updated/completed at runtime via a BufferField. 233124f4c82Sjruoho * 234124f4c82Sjruoho * If the descriptor does NOT have a resource tag, it cannot be referenced 235124f4c82Sjruoho * by a BufferField and we will flag this as an error. Conversely, if 236124f4c82Sjruoho * the descriptor has a resource tag, we will assume that a BufferField 237124f4c82Sjruoho * will be used to dynamically update it, so no error. 238124f4c82Sjruoho * 239124f4c82Sjruoho * A possible enhancement to this check would be to verify that in fact 240124f4c82Sjruoho * a BufferField is created using the resource tag, and perhaps even 241124f4c82Sjruoho * verify that a Store is performed to the BufferField. 242124f4c82Sjruoho */ 243124f4c82Sjruoho if (!Minimum && !Maximum && !Length && !Granularity) 244124f4c82Sjruoho { 245124f4c82Sjruoho if (!Op->Asl.ExternalName) 246124f4c82Sjruoho { 247124f4c82Sjruoho /* No resource tag. Descriptor is fixed and is also illegal */ 248124f4c82Sjruoho 249124f4c82Sjruoho AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL); 250124f4c82Sjruoho } 251124f4c82Sjruoho 252124f4c82Sjruoho return; 253124f4c82Sjruoho } 254124f4c82Sjruoho 25528c506b8Sjruoho /* Basic checks on Min/Max/Length */ 25628c506b8Sjruoho 25728c506b8Sjruoho if (Minimum > Maximum) 25828c506b8Sjruoho { 25928c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); 26028c506b8Sjruoho return; 26128c506b8Sjruoho } 26228c506b8Sjruoho else if (Length > (Maximum - Minimum + 1)) 26328c506b8Sjruoho { 26428c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); 26528c506b8Sjruoho return; 26628c506b8Sjruoho } 26728c506b8Sjruoho 26828c506b8Sjruoho /* If specified (non-zero), ensure granularity is a power-of-two minus one */ 26928c506b8Sjruoho 27028c506b8Sjruoho if (Granularity) 27128c506b8Sjruoho { 27228c506b8Sjruoho if ((Granularity + 1) & 27328c506b8Sjruoho Granularity) 27428c506b8Sjruoho { 27528c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL); 27628c506b8Sjruoho return; 27728c506b8Sjruoho } 27828c506b8Sjruoho } 27928c506b8Sjruoho 28028c506b8Sjruoho /* 28128c506b8Sjruoho * Check the various combinations of Length, MinFixed, and MaxFixed 28228c506b8Sjruoho */ 28328c506b8Sjruoho if (Length) 28428c506b8Sjruoho { 28528c506b8Sjruoho /* Fixed non-zero length */ 28628c506b8Sjruoho 28728c506b8Sjruoho switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) 28828c506b8Sjruoho { 28928c506b8Sjruoho case 0: 29028c506b8Sjruoho /* 29128c506b8Sjruoho * Fixed length, variable locations (both _MIN and _MAX). 29228c506b8Sjruoho * Length must be a multiple of granularity 29328c506b8Sjruoho */ 29428c506b8Sjruoho if (Granularity & Length) 29528c506b8Sjruoho { 29628c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL); 29728c506b8Sjruoho } 29828c506b8Sjruoho break; 29928c506b8Sjruoho 30028c506b8Sjruoho case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): 30128c506b8Sjruoho 30228c506b8Sjruoho /* Fixed length, fixed location. Granularity must be zero */ 30328c506b8Sjruoho 30428c506b8Sjruoho if (Granularity != 0) 30528c506b8Sjruoho { 30628c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL); 30728c506b8Sjruoho } 30828c506b8Sjruoho 30928c506b8Sjruoho /* Length must be exactly the size of the min/max window */ 31028c506b8Sjruoho 31128c506b8Sjruoho if (Length != (Maximum - Minimum + 1)) 31228c506b8Sjruoho { 31328c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL); 31428c506b8Sjruoho } 31528c506b8Sjruoho break; 31628c506b8Sjruoho 31728c506b8Sjruoho /* All other combinations are invalid */ 31828c506b8Sjruoho 31928c506b8Sjruoho case ACPI_RESOURCE_FLAG_MIF: 32028c506b8Sjruoho case ACPI_RESOURCE_FLAG_MAF: 32128c506b8Sjruoho default: 322ff4a156dSchristos 32328c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); 32428c506b8Sjruoho } 32528c506b8Sjruoho } 32628c506b8Sjruoho else 32728c506b8Sjruoho { 32828c506b8Sjruoho /* Variable length (length==0) */ 32928c506b8Sjruoho 33028c506b8Sjruoho switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) 33128c506b8Sjruoho { 33228c506b8Sjruoho case 0: 33328c506b8Sjruoho /* 33428c506b8Sjruoho * Both _MIN and _MAX are variable. 33528c506b8Sjruoho * No additional requirements, just exit 33628c506b8Sjruoho */ 33728c506b8Sjruoho break; 33828c506b8Sjruoho 33928c506b8Sjruoho case ACPI_RESOURCE_FLAG_MIF: 34028c506b8Sjruoho 34128c506b8Sjruoho /* _MIN is fixed. _MIN must be multiple of _GRA */ 34228c506b8Sjruoho 34328c506b8Sjruoho /* 34428c506b8Sjruoho * The granularity is defined by the ACPI specification to be a 34528c506b8Sjruoho * power-of-two minus one, therefore the granularity is a 34628c506b8Sjruoho * bitmask which can be used to easily validate the addresses. 34728c506b8Sjruoho */ 34828c506b8Sjruoho if (Granularity & Minimum) 34928c506b8Sjruoho { 35028c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); 35128c506b8Sjruoho } 35228c506b8Sjruoho break; 35328c506b8Sjruoho 35428c506b8Sjruoho case ACPI_RESOURCE_FLAG_MAF: 35528c506b8Sjruoho 35628c506b8Sjruoho /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */ 35728c506b8Sjruoho 35828c506b8Sjruoho if (Granularity & (Maximum + 1)) 35928c506b8Sjruoho { 36028c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1"); 36128c506b8Sjruoho } 36228c506b8Sjruoho break; 36328c506b8Sjruoho 36428c506b8Sjruoho /* Both MIF/MAF set is invalid if length is zero */ 36528c506b8Sjruoho 36628c506b8Sjruoho case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): 36728c506b8Sjruoho default: 368ff4a156dSchristos 36928c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); 37028c506b8Sjruoho } 37128c506b8Sjruoho } 37228c506b8Sjruoho } 37328c506b8Sjruoho 37428c506b8Sjruoho 37528c506b8Sjruoho /******************************************************************************* 37628c506b8Sjruoho * 37728c506b8Sjruoho * FUNCTION: RsGetStringDataLength 37828c506b8Sjruoho * 37928c506b8Sjruoho * PARAMETERS: InitializerOp - Start of a subtree of init nodes 38028c506b8Sjruoho * 38128c506b8Sjruoho * RETURN: Valid string length if a string node is found (otherwise 0) 38228c506b8Sjruoho * 38328c506b8Sjruoho * DESCRIPTION: In a list of peer nodes, find the first one that contains a 38428c506b8Sjruoho * string and return the length of the string. 38528c506b8Sjruoho * 38628c506b8Sjruoho ******************************************************************************/ 38728c506b8Sjruoho 38828c506b8Sjruoho UINT16 38928c506b8Sjruoho RsGetStringDataLength ( 39028c506b8Sjruoho ACPI_PARSE_OBJECT *InitializerOp) 39128c506b8Sjruoho { 39228c506b8Sjruoho 39328c506b8Sjruoho while (InitializerOp) 39428c506b8Sjruoho { 39528c506b8Sjruoho if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) 39628c506b8Sjruoho { 39728c506b8Sjruoho return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1)); 39828c506b8Sjruoho } 39971e38f1dSchristos 40028c506b8Sjruoho InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 40128c506b8Sjruoho } 40228c506b8Sjruoho 403ff4a156dSchristos return (0); 40428c506b8Sjruoho } 40528c506b8Sjruoho 40628c506b8Sjruoho 40728c506b8Sjruoho /******************************************************************************* 40828c506b8Sjruoho * 40928c506b8Sjruoho * FUNCTION: RsAllocateResourceNode 41028c506b8Sjruoho * 41128c506b8Sjruoho * PARAMETERS: Size - Size of node in bytes 41228c506b8Sjruoho * 41328c506b8Sjruoho * RETURN: The allocated node - aborts on allocation failure 41428c506b8Sjruoho * 41528c506b8Sjruoho * DESCRIPTION: Allocate a resource description node and the resource 41628c506b8Sjruoho * descriptor itself (the nodes are used to link descriptors). 41728c506b8Sjruoho * 41828c506b8Sjruoho ******************************************************************************/ 41928c506b8Sjruoho 42028c506b8Sjruoho ASL_RESOURCE_NODE * 42128c506b8Sjruoho RsAllocateResourceNode ( 42228c506b8Sjruoho UINT32 Size) 42328c506b8Sjruoho { 42428c506b8Sjruoho ASL_RESOURCE_NODE *Rnode; 42528c506b8Sjruoho 42628c506b8Sjruoho 42728c506b8Sjruoho /* Allocate the node */ 42828c506b8Sjruoho 42928c506b8Sjruoho Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE)); 43028c506b8Sjruoho 43128c506b8Sjruoho /* Allocate the resource descriptor itself */ 43228c506b8Sjruoho 43328c506b8Sjruoho Rnode->Buffer = UtLocalCalloc (Size); 43428c506b8Sjruoho Rnode->BufferLength = Size; 43528c506b8Sjruoho return (Rnode); 43628c506b8Sjruoho } 43728c506b8Sjruoho 43828c506b8Sjruoho 43928c506b8Sjruoho /******************************************************************************* 44028c506b8Sjruoho * 441ff4a156dSchristos * FUNCTION: RsCreateResourceField 44228c506b8Sjruoho * 44328c506b8Sjruoho * PARAMETERS: Op - Resource field node 44428c506b8Sjruoho * Name - Name of the field (Used only to reference 44528c506b8Sjruoho * the field in the ASL, not in the AML) 44628c506b8Sjruoho * ByteOffset - Offset from the field start 44728c506b8Sjruoho * BitOffset - Additional bit offset 448ff4a156dSchristos * BitLength - Number of bits in the field 44928c506b8Sjruoho * 45028c506b8Sjruoho * RETURN: None, sets fields within the input node 45128c506b8Sjruoho * 45228c506b8Sjruoho * DESCRIPTION: Utility function to generate a named bit field within a 45328c506b8Sjruoho * resource descriptor. Mark a node as 1) a field in a resource 45428c506b8Sjruoho * descriptor, and 2) set the value to be a BIT offset 45528c506b8Sjruoho * 45628c506b8Sjruoho ******************************************************************************/ 45728c506b8Sjruoho 45828c506b8Sjruoho void 459ff4a156dSchristos RsCreateResourceField ( 46028c506b8Sjruoho ACPI_PARSE_OBJECT *Op, 46128c506b8Sjruoho char *Name, 46228c506b8Sjruoho UINT32 ByteOffset, 463ff4a156dSchristos UINT32 BitOffset, 464ff4a156dSchristos UINT32 BitLength) 46528c506b8Sjruoho { 46628c506b8Sjruoho 46728c506b8Sjruoho Op->Asl.ExternalName = Name; 46889b8eb6cSchristos Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD; 469ff4a156dSchristos 470ff4a156dSchristos Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset; 471ff4a156dSchristos Op->Asl.Value.Tag.BitLength = BitLength; 47228c506b8Sjruoho } 47328c506b8Sjruoho 47428c506b8Sjruoho 47528c506b8Sjruoho /******************************************************************************* 47628c506b8Sjruoho * 47728c506b8Sjruoho * FUNCTION: RsSetFlagBits 47828c506b8Sjruoho * 47928c506b8Sjruoho * PARAMETERS: *Flags - Pointer to the flag byte 48028c506b8Sjruoho * Op - Flag initialization node 48128c506b8Sjruoho * Position - Bit position within the flag byte 48228c506b8Sjruoho * Default - Used if the node is DEFAULT. 48328c506b8Sjruoho * 48428c506b8Sjruoho * RETURN: Sets bits within the *Flags output byte. 48528c506b8Sjruoho * 48628c506b8Sjruoho * DESCRIPTION: Set a bit in a cumulative flags word from an initialization 48728c506b8Sjruoho * node. Will use a default value if the node is DEFAULT, meaning 48828c506b8Sjruoho * that no value was specified in the ASL. Used to merge multiple 48928c506b8Sjruoho * keywords into a single flags byte. 49028c506b8Sjruoho * 49128c506b8Sjruoho ******************************************************************************/ 49228c506b8Sjruoho 49328c506b8Sjruoho void 49428c506b8Sjruoho RsSetFlagBits ( 49528c506b8Sjruoho UINT8 *Flags, 49628c506b8Sjruoho ACPI_PARSE_OBJECT *Op, 49728c506b8Sjruoho UINT8 Position, 49828c506b8Sjruoho UINT8 DefaultBit) 49928c506b8Sjruoho { 50028c506b8Sjruoho 50128c506b8Sjruoho if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 50228c506b8Sjruoho { 50328c506b8Sjruoho /* Use the default bit */ 50428c506b8Sjruoho 50528c506b8Sjruoho *Flags |= (DefaultBit << Position); 50628c506b8Sjruoho } 50728c506b8Sjruoho else 50828c506b8Sjruoho { 50928c506b8Sjruoho /* Use the bit specified in the initialization node */ 51028c506b8Sjruoho 51128c506b8Sjruoho *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position); 51228c506b8Sjruoho } 51328c506b8Sjruoho } 51428c506b8Sjruoho 51528c506b8Sjruoho 516ff4a156dSchristos void 517ff4a156dSchristos RsSetFlagBits16 ( 518ff4a156dSchristos UINT16 *Flags, 519ff4a156dSchristos ACPI_PARSE_OBJECT *Op, 520ff4a156dSchristos UINT8 Position, 521ff4a156dSchristos UINT8 DefaultBit) 522ff4a156dSchristos { 523ff4a156dSchristos 524ff4a156dSchristos if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 525ff4a156dSchristos { 526ff4a156dSchristos /* Use the default bit */ 527ff4a156dSchristos 528ff4a156dSchristos *Flags |= (DefaultBit << Position); 529ff4a156dSchristos } 530ff4a156dSchristos else 531ff4a156dSchristos { 532ff4a156dSchristos /* Use the bit specified in the initialization node */ 533ff4a156dSchristos 534ff4a156dSchristos *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position); 535ff4a156dSchristos } 536ff4a156dSchristos } 537ff4a156dSchristos 538ff4a156dSchristos 53928c506b8Sjruoho /******************************************************************************* 54028c506b8Sjruoho * 54128c506b8Sjruoho * FUNCTION: RsCompleteNodeAndGetNext 54228c506b8Sjruoho * 54328c506b8Sjruoho * PARAMETERS: Op - Resource node to be completed 54428c506b8Sjruoho * 54528c506b8Sjruoho * RETURN: The next peer to the input node. 54628c506b8Sjruoho * 54728c506b8Sjruoho * DESCRIPTION: Mark the current node completed and return the next peer. 54828c506b8Sjruoho * The node ParseOpcode is set to DEFAULT_ARG, meaning that 54928c506b8Sjruoho * this node is to be ignored from now on. 55028c506b8Sjruoho * 55128c506b8Sjruoho ******************************************************************************/ 55228c506b8Sjruoho 55328c506b8Sjruoho ACPI_PARSE_OBJECT * 55428c506b8Sjruoho RsCompleteNodeAndGetNext ( 55528c506b8Sjruoho ACPI_PARSE_OBJECT *Op) 55628c506b8Sjruoho { 55728c506b8Sjruoho 55828c506b8Sjruoho /* Mark this node unused */ 55928c506b8Sjruoho 56028c506b8Sjruoho Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 56128c506b8Sjruoho 56228c506b8Sjruoho /* Move on to the next peer node in the initializer list */ 56328c506b8Sjruoho 56428c506b8Sjruoho return (ASL_GET_PEER_NODE (Op)); 56528c506b8Sjruoho } 56628c506b8Sjruoho 56728c506b8Sjruoho 56828c506b8Sjruoho /******************************************************************************* 56928c506b8Sjruoho * 57028c506b8Sjruoho * FUNCTION: RsCheckListForDuplicates 57128c506b8Sjruoho * 57228c506b8Sjruoho * PARAMETERS: Op - First op in the initializer list 57328c506b8Sjruoho * 57428c506b8Sjruoho * RETURN: None 57528c506b8Sjruoho * 57628c506b8Sjruoho * DESCRIPTION: Check an initializer list for duplicate values. Emits an error 57728c506b8Sjruoho * if any duplicates are found. 57828c506b8Sjruoho * 57928c506b8Sjruoho ******************************************************************************/ 58028c506b8Sjruoho 58128c506b8Sjruoho void 58228c506b8Sjruoho RsCheckListForDuplicates ( 58328c506b8Sjruoho ACPI_PARSE_OBJECT *Op) 58428c506b8Sjruoho { 58528c506b8Sjruoho ACPI_PARSE_OBJECT *NextValueOp = Op; 58628c506b8Sjruoho ACPI_PARSE_OBJECT *NextOp; 58728c506b8Sjruoho UINT32 Value; 58828c506b8Sjruoho 58928c506b8Sjruoho 59028c506b8Sjruoho if (!Op) 59128c506b8Sjruoho { 59228c506b8Sjruoho return; 59328c506b8Sjruoho } 59428c506b8Sjruoho 59528c506b8Sjruoho /* Search list once for each value in the list */ 59628c506b8Sjruoho 59728c506b8Sjruoho while (NextValueOp) 59828c506b8Sjruoho { 59928c506b8Sjruoho Value = (UINT32) NextValueOp->Asl.Value.Integer; 60028c506b8Sjruoho 60128c506b8Sjruoho /* Compare this value to all remaining values in the list */ 60228c506b8Sjruoho 60328c506b8Sjruoho NextOp = ASL_GET_PEER_NODE (NextValueOp); 60428c506b8Sjruoho while (NextOp) 60528c506b8Sjruoho { 60628c506b8Sjruoho if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 60728c506b8Sjruoho { 60828c506b8Sjruoho /* Compare values */ 60928c506b8Sjruoho 61028c506b8Sjruoho if (Value == (UINT32) NextOp->Asl.Value.Integer) 61128c506b8Sjruoho { 61228c506b8Sjruoho /* Emit error only once per duplicate node */ 61328c506b8Sjruoho 61489b8eb6cSchristos if (!(NextOp->Asl.CompileFlags & OP_IS_DUPLICATE)) 61528c506b8Sjruoho { 61689b8eb6cSchristos NextOp->Asl.CompileFlags |= OP_IS_DUPLICATE; 61728c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM, 61828c506b8Sjruoho NextOp, NULL); 61928c506b8Sjruoho } 62028c506b8Sjruoho } 62128c506b8Sjruoho } 62228c506b8Sjruoho 62328c506b8Sjruoho NextOp = ASL_GET_PEER_NODE (NextOp); 62428c506b8Sjruoho } 62528c506b8Sjruoho 62628c506b8Sjruoho NextValueOp = ASL_GET_PEER_NODE (NextValueOp); 62728c506b8Sjruoho } 62828c506b8Sjruoho } 62928c506b8Sjruoho 63028c506b8Sjruoho 63128c506b8Sjruoho /******************************************************************************* 63228c506b8Sjruoho * 63328c506b8Sjruoho * FUNCTION: RsDoOneResourceDescriptor 63428c506b8Sjruoho * 63528c506b8Sjruoho * PARAMETERS: DescriptorTypeOp - Parent parse node of the descriptor 63628c506b8Sjruoho * CurrentByteOffset - Offset in the resource descriptor 63728c506b8Sjruoho * buffer. 63828c506b8Sjruoho * 63928c506b8Sjruoho * RETURN: A valid resource node for the descriptor 64028c506b8Sjruoho * 64128c506b8Sjruoho * DESCRIPTION: Dispatches the processing of one resource descriptor 64228c506b8Sjruoho * 64328c506b8Sjruoho ******************************************************************************/ 64428c506b8Sjruoho 64528c506b8Sjruoho ASL_RESOURCE_NODE * 64628c506b8Sjruoho RsDoOneResourceDescriptor ( 647460301d4Schristos ASL_RESOURCE_INFO *Info, 64828c506b8Sjruoho UINT8 *State) 64928c506b8Sjruoho { 65028c506b8Sjruoho ASL_RESOURCE_NODE *Rnode = NULL; 65128c506b8Sjruoho 65228c506b8Sjruoho 65328c506b8Sjruoho /* Construct the resource */ 65428c506b8Sjruoho 655460301d4Schristos switch (Info->DescriptorTypeOp->Asl.ParseOpcode) 65628c506b8Sjruoho { 657046a2985Schristos 658046a2985Schristos case PARSEOP_CLOCKINPUT: 659046a2985Schristos 660046a2985Schristos Rnode = RsDoClockInputDescriptor(Info); 661046a2985Schristos break; 662046a2985Schristos 66328c506b8Sjruoho case PARSEOP_DMA: 664ff4a156dSchristos 665460301d4Schristos Rnode = RsDoDmaDescriptor (Info); 66628c506b8Sjruoho break; 66728c506b8Sjruoho 668ff4a156dSchristos case PARSEOP_FIXEDDMA: 669ff4a156dSchristos 670460301d4Schristos Rnode = RsDoFixedDmaDescriptor (Info); 671ff4a156dSchristos break; 672ff4a156dSchristos 67328c506b8Sjruoho case PARSEOP_DWORDIO: 674ff4a156dSchristos 675460301d4Schristos Rnode = RsDoDwordIoDescriptor (Info); 67628c506b8Sjruoho break; 67728c506b8Sjruoho 67828c506b8Sjruoho case PARSEOP_DWORDMEMORY: 679ff4a156dSchristos 680460301d4Schristos Rnode = RsDoDwordMemoryDescriptor (Info); 68128c506b8Sjruoho break; 68228c506b8Sjruoho 683*c7960b37Schristos case PARSEOP_DWORDPCC: 684*c7960b37Schristos 685*c7960b37Schristos Rnode = RsDoDwordPccDescriptor (Info); 686*c7960b37Schristos break; 687*c7960b37Schristos 68828c506b8Sjruoho case PARSEOP_DWORDSPACE: 689ff4a156dSchristos 690460301d4Schristos Rnode = RsDoDwordSpaceDescriptor (Info); 69128c506b8Sjruoho break; 69228c506b8Sjruoho 69328c506b8Sjruoho case PARSEOP_ENDDEPENDENTFN: 694ff4a156dSchristos 69528c506b8Sjruoho switch (*State) 69628c506b8Sjruoho { 69728c506b8Sjruoho case ACPI_RSTATE_NORMAL: 698ff4a156dSchristos 69928c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT, 700460301d4Schristos Info->DescriptorTypeOp, NULL); 70128c506b8Sjruoho break; 70228c506b8Sjruoho 70328c506b8Sjruoho case ACPI_RSTATE_START_DEPENDENT: 704ff4a156dSchristos 70528c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, 706460301d4Schristos Info->DescriptorTypeOp, NULL); 70728c506b8Sjruoho break; 70828c506b8Sjruoho 70928c506b8Sjruoho case ACPI_RSTATE_DEPENDENT_LIST: 71028c506b8Sjruoho default: 711ff4a156dSchristos 71228c506b8Sjruoho break; 71328c506b8Sjruoho } 71428c506b8Sjruoho 71528c506b8Sjruoho *State = ACPI_RSTATE_NORMAL; 716460301d4Schristos Rnode = RsDoEndDependentDescriptor (Info); 71728c506b8Sjruoho break; 71828c506b8Sjruoho 71928c506b8Sjruoho case PARSEOP_ENDTAG: 720ff4a156dSchristos 721460301d4Schristos Rnode = RsDoEndTagDescriptor (Info); 72228c506b8Sjruoho break; 72328c506b8Sjruoho 72428c506b8Sjruoho case PARSEOP_EXTENDEDIO: 725ff4a156dSchristos 726460301d4Schristos Rnode = RsDoExtendedIoDescriptor (Info); 72728c506b8Sjruoho break; 72828c506b8Sjruoho 72928c506b8Sjruoho case PARSEOP_EXTENDEDMEMORY: 730ff4a156dSchristos 731460301d4Schristos Rnode = RsDoExtendedMemoryDescriptor (Info); 73228c506b8Sjruoho break; 73328c506b8Sjruoho 73428c506b8Sjruoho case PARSEOP_EXTENDEDSPACE: 735ff4a156dSchristos 736460301d4Schristos Rnode = RsDoExtendedSpaceDescriptor (Info); 73728c506b8Sjruoho break; 73828c506b8Sjruoho 73928c506b8Sjruoho case PARSEOP_FIXEDIO: 740ff4a156dSchristos 741460301d4Schristos Rnode = RsDoFixedIoDescriptor (Info); 74228c506b8Sjruoho break; 74328c506b8Sjruoho 74428c506b8Sjruoho case PARSEOP_INTERRUPT: 745ff4a156dSchristos 746460301d4Schristos Rnode = RsDoInterruptDescriptor (Info); 74728c506b8Sjruoho break; 74828c506b8Sjruoho 74928c506b8Sjruoho case PARSEOP_IO: 750ff4a156dSchristos 751460301d4Schristos Rnode = RsDoIoDescriptor (Info); 75228c506b8Sjruoho break; 75328c506b8Sjruoho 75428c506b8Sjruoho case PARSEOP_IRQ: 755ff4a156dSchristos 756460301d4Schristos Rnode = RsDoIrqDescriptor (Info); 75728c506b8Sjruoho break; 75828c506b8Sjruoho 75928c506b8Sjruoho case PARSEOP_IRQNOFLAGS: 760ff4a156dSchristos 761460301d4Schristos Rnode = RsDoIrqNoFlagsDescriptor (Info); 76228c506b8Sjruoho break; 76328c506b8Sjruoho 76428c506b8Sjruoho case PARSEOP_MEMORY24: 765ff4a156dSchristos 766460301d4Schristos Rnode = RsDoMemory24Descriptor (Info); 76728c506b8Sjruoho break; 76828c506b8Sjruoho 76928c506b8Sjruoho case PARSEOP_MEMORY32: 770ff4a156dSchristos 771460301d4Schristos Rnode = RsDoMemory32Descriptor (Info); 77228c506b8Sjruoho break; 77328c506b8Sjruoho 77428c506b8Sjruoho case PARSEOP_MEMORY32FIXED: 775ff4a156dSchristos 776460301d4Schristos Rnode = RsDoMemory32FixedDescriptor (Info); 77728c506b8Sjruoho break; 77828c506b8Sjruoho 77928c506b8Sjruoho case PARSEOP_QWORDIO: 780ff4a156dSchristos 781460301d4Schristos Rnode = RsDoQwordIoDescriptor (Info); 78228c506b8Sjruoho break; 78328c506b8Sjruoho 78428c506b8Sjruoho case PARSEOP_QWORDMEMORY: 785ff4a156dSchristos 786460301d4Schristos Rnode = RsDoQwordMemoryDescriptor (Info); 78728c506b8Sjruoho break; 78828c506b8Sjruoho 789*c7960b37Schristos case PARSEOP_QWORDPCC: 790*c7960b37Schristos 791*c7960b37Schristos Rnode = RsDoQwordPccDescriptor (Info); 792*c7960b37Schristos break; 793*c7960b37Schristos 79428c506b8Sjruoho case PARSEOP_QWORDSPACE: 795ff4a156dSchristos 796460301d4Schristos Rnode = RsDoQwordSpaceDescriptor (Info); 79728c506b8Sjruoho break; 79828c506b8Sjruoho 79928c506b8Sjruoho case PARSEOP_REGISTER: 800ff4a156dSchristos 801460301d4Schristos Rnode = RsDoGeneralRegisterDescriptor (Info); 80228c506b8Sjruoho break; 80328c506b8Sjruoho 80428c506b8Sjruoho case PARSEOP_STARTDEPENDENTFN: 805ff4a156dSchristos 80628c506b8Sjruoho switch (*State) 80728c506b8Sjruoho { 80828c506b8Sjruoho case ACPI_RSTATE_START_DEPENDENT: 809ff4a156dSchristos 81028c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, 811460301d4Schristos Info->DescriptorTypeOp, NULL); 81228c506b8Sjruoho break; 81328c506b8Sjruoho 81428c506b8Sjruoho case ACPI_RSTATE_NORMAL: 81528c506b8Sjruoho case ACPI_RSTATE_DEPENDENT_LIST: 81628c506b8Sjruoho default: 817ff4a156dSchristos 81828c506b8Sjruoho break; 81928c506b8Sjruoho } 82028c506b8Sjruoho 82128c506b8Sjruoho *State = ACPI_RSTATE_START_DEPENDENT; 822460301d4Schristos Rnode = RsDoStartDependentDescriptor (Info); 82328c506b8Sjruoho *State = ACPI_RSTATE_DEPENDENT_LIST; 82428c506b8Sjruoho break; 82528c506b8Sjruoho 82628c506b8Sjruoho case PARSEOP_STARTDEPENDENTFN_NOPRI: 827ff4a156dSchristos 82828c506b8Sjruoho switch (*State) 82928c506b8Sjruoho { 83028c506b8Sjruoho case ACPI_RSTATE_START_DEPENDENT: 831ff4a156dSchristos 83228c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING, 833460301d4Schristos Info->DescriptorTypeOp, NULL); 83428c506b8Sjruoho break; 83528c506b8Sjruoho 83628c506b8Sjruoho case ACPI_RSTATE_NORMAL: 83728c506b8Sjruoho case ACPI_RSTATE_DEPENDENT_LIST: 83828c506b8Sjruoho default: 839ff4a156dSchristos 84028c506b8Sjruoho break; 84128c506b8Sjruoho } 84228c506b8Sjruoho 84328c506b8Sjruoho *State = ACPI_RSTATE_START_DEPENDENT; 844460301d4Schristos Rnode = RsDoStartDependentNoPriDescriptor (Info); 84528c506b8Sjruoho *State = ACPI_RSTATE_DEPENDENT_LIST; 84628c506b8Sjruoho break; 84728c506b8Sjruoho 84828c506b8Sjruoho case PARSEOP_VENDORLONG: 849ff4a156dSchristos 850460301d4Schristos Rnode = RsDoVendorLargeDescriptor (Info); 85128c506b8Sjruoho break; 85228c506b8Sjruoho 85328c506b8Sjruoho case PARSEOP_VENDORSHORT: 854ff4a156dSchristos 855460301d4Schristos Rnode = RsDoVendorSmallDescriptor (Info); 85628c506b8Sjruoho break; 85728c506b8Sjruoho 85828c506b8Sjruoho case PARSEOP_WORDBUSNUMBER: 859ff4a156dSchristos 860460301d4Schristos Rnode = RsDoWordBusNumberDescriptor (Info); 86128c506b8Sjruoho break; 86228c506b8Sjruoho 86328c506b8Sjruoho case PARSEOP_WORDIO: 864ff4a156dSchristos 865460301d4Schristos Rnode = RsDoWordIoDescriptor (Info); 86628c506b8Sjruoho break; 86728c506b8Sjruoho 868*c7960b37Schristos case PARSEOP_WORDPCC: 869*c7960b37Schristos 870*c7960b37Schristos Rnode = RsDoWordPccDescriptor (Info); 871*c7960b37Schristos break; 872*c7960b37Schristos 87328c506b8Sjruoho case PARSEOP_WORDSPACE: 874ff4a156dSchristos 875460301d4Schristos Rnode = RsDoWordSpaceDescriptor (Info); 87628c506b8Sjruoho break; 87728c506b8Sjruoho 878ff4a156dSchristos case PARSEOP_GPIO_INT: 879ff4a156dSchristos 880460301d4Schristos Rnode = RsDoGpioIntDescriptor (Info); 881ff4a156dSchristos break; 882ff4a156dSchristos 883ff4a156dSchristos case PARSEOP_GPIO_IO: 884ff4a156dSchristos 885460301d4Schristos Rnode = RsDoGpioIoDescriptor (Info); 886ff4a156dSchristos break; 887ff4a156dSchristos 888ff4a156dSchristos case PARSEOP_I2C_SERIALBUS: 889cfbb7280Schristos case PARSEOP_I2C_SERIALBUS_V2: 890ff4a156dSchristos 891460301d4Schristos Rnode = RsDoI2cSerialBusDescriptor (Info); 892ff4a156dSchristos break; 893ff4a156dSchristos 894ff4a156dSchristos case PARSEOP_SPI_SERIALBUS: 895cfbb7280Schristos case PARSEOP_SPI_SERIALBUS_V2: 896ff4a156dSchristos 897460301d4Schristos Rnode = RsDoSpiSerialBusDescriptor (Info); 898ff4a156dSchristos break; 899ff4a156dSchristos 900ff4a156dSchristos case PARSEOP_UART_SERIALBUS: 901cfbb7280Schristos case PARSEOP_UART_SERIALBUS_V2: 902ff4a156dSchristos 903460301d4Schristos Rnode = RsDoUartSerialBusDescriptor (Info); 904ff4a156dSchristos break; 905ff4a156dSchristos 90646a330b4Schristos case PARSEOP_CSI2_SERIALBUS: 90746a330b4Schristos 90846a330b4Schristos Rnode = RsDoCsi2SerialBusDescriptor (Info); 90946a330b4Schristos break; 91046a330b4Schristos 91189b8eb6cSchristos case PARSEOP_PINCONFIG: 91289b8eb6cSchristos 91389b8eb6cSchristos Rnode = RsDoPinConfigDescriptor (Info); 91489b8eb6cSchristos break; 91589b8eb6cSchristos 91689b8eb6cSchristos case PARSEOP_PINFUNCTION: 91789b8eb6cSchristos 91889b8eb6cSchristos Rnode = RsDoPinFunctionDescriptor (Info); 91989b8eb6cSchristos break; 92089b8eb6cSchristos 92189b8eb6cSchristos case PARSEOP_PINGROUP: 92289b8eb6cSchristos 92389b8eb6cSchristos Rnode = RsDoPinGroupDescriptor (Info); 92489b8eb6cSchristos break; 92589b8eb6cSchristos 92689b8eb6cSchristos case PARSEOP_PINGROUPFUNCTION: 92789b8eb6cSchristos 92889b8eb6cSchristos Rnode = RsDoPinGroupFunctionDescriptor (Info); 92989b8eb6cSchristos break; 93089b8eb6cSchristos 93189b8eb6cSchristos case PARSEOP_PINGROUPCONFIG: 93289b8eb6cSchristos 93389b8eb6cSchristos Rnode = RsDoPinGroupConfigDescriptor (Info); 93489b8eb6cSchristos break; 93589b8eb6cSchristos 93628c506b8Sjruoho case PARSEOP_DEFAULT_ARG: 937ff4a156dSchristos 93828c506b8Sjruoho /* Just ignore any of these, they are used as fillers/placeholders */ 93928c506b8Sjruoho break; 94028c506b8Sjruoho 94128c506b8Sjruoho default: 942ff4a156dSchristos 94328c506b8Sjruoho printf ("Unknown resource descriptor type [%s]\n", 944460301d4Schristos Info->DescriptorTypeOp->Asl.ParseOpName); 94528c506b8Sjruoho break; 94628c506b8Sjruoho } 94728c506b8Sjruoho 94828c506b8Sjruoho /* 94928c506b8Sjruoho * Mark original node as unused, but head of a resource descriptor. 95028c506b8Sjruoho * This allows the resource to be installed in the namespace so that 95128c506b8Sjruoho * references to the descriptor can be resolved. 95228c506b8Sjruoho */ 953460301d4Schristos Info->DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 95489b8eb6cSchristos Info->DescriptorTypeOp->Asl.CompileFlags = OP_IS_RESOURCE_DESC; 955460301d4Schristos Info->DescriptorTypeOp->Asl.Value.Integer = Info->CurrentByteOffset; 95628c506b8Sjruoho 95728c506b8Sjruoho if (Rnode) 95828c506b8Sjruoho { 959460301d4Schristos Info->DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength; 96071e38f1dSchristos Info->DescriptorTypeOp->Asl.Extra = 96171e38f1dSchristos ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType; 96228c506b8Sjruoho } 96328c506b8Sjruoho 96428c506b8Sjruoho return (Rnode); 96528c506b8Sjruoho } 96628c506b8Sjruoho 96728c506b8Sjruoho 96828c506b8Sjruoho /******************************************************************************* 96928c506b8Sjruoho * 97028c506b8Sjruoho * FUNCTION: RsLinkDescriptorChain 97128c506b8Sjruoho * 97228c506b8Sjruoho * PARAMETERS: PreviousRnode - Pointer to the node that will be previous 97328c506b8Sjruoho * to the linked node, At exit, set to the 97428c506b8Sjruoho * last node in the new chain. 97528c506b8Sjruoho * Rnode - Resource node to link into the list 97628c506b8Sjruoho * 97728c506b8Sjruoho * RETURN: Cumulative buffer byte offset of the new segment of chain 97828c506b8Sjruoho * 97928c506b8Sjruoho * DESCRIPTION: Link a descriptor chain at the end of an existing chain. 98028c506b8Sjruoho * 98128c506b8Sjruoho ******************************************************************************/ 98228c506b8Sjruoho 98328c506b8Sjruoho UINT32 98428c506b8Sjruoho RsLinkDescriptorChain ( 98528c506b8Sjruoho ASL_RESOURCE_NODE **PreviousRnode, 98628c506b8Sjruoho ASL_RESOURCE_NODE *Rnode) 98728c506b8Sjruoho { 98828c506b8Sjruoho ASL_RESOURCE_NODE *LastRnode; 98928c506b8Sjruoho UINT32 CurrentByteOffset; 99028c506b8Sjruoho 99128c506b8Sjruoho 99228c506b8Sjruoho /* Anything to do? */ 99328c506b8Sjruoho 99428c506b8Sjruoho if (!Rnode) 99528c506b8Sjruoho { 996ff4a156dSchristos return (0); 99728c506b8Sjruoho } 99828c506b8Sjruoho 99928c506b8Sjruoho /* Point the previous node to the new node */ 100028c506b8Sjruoho 100128c506b8Sjruoho (*PreviousRnode)->Next = Rnode; 100228c506b8Sjruoho CurrentByteOffset = Rnode->BufferLength; 100328c506b8Sjruoho 100428c506b8Sjruoho /* Walk to the end of the chain headed by Rnode */ 100528c506b8Sjruoho 100628c506b8Sjruoho LastRnode = Rnode; 100728c506b8Sjruoho while (LastRnode->Next) 100828c506b8Sjruoho { 100928c506b8Sjruoho LastRnode = LastRnode->Next; 101028c506b8Sjruoho CurrentByteOffset += LastRnode->BufferLength; 101128c506b8Sjruoho } 101228c506b8Sjruoho 101328c506b8Sjruoho /* Previous node becomes the last node in the chain */ 101428c506b8Sjruoho 101528c506b8Sjruoho *PreviousRnode = LastRnode; 1016ff4a156dSchristos return (CurrentByteOffset); 101728c506b8Sjruoho } 101828c506b8Sjruoho 101928c506b8Sjruoho 102028c506b8Sjruoho /******************************************************************************* 102128c506b8Sjruoho * 102228c506b8Sjruoho * FUNCTION: RsDoResourceTemplate 102328c506b8Sjruoho * 102428c506b8Sjruoho * PARAMETERS: Op - Parent of a resource template list 102528c506b8Sjruoho * 102628c506b8Sjruoho * RETURN: None. Sets input node to point to a list of AML code 102728c506b8Sjruoho * 102828c506b8Sjruoho * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer, 102928c506b8Sjruoho * in preparation for output to the AML output file. 103028c506b8Sjruoho * 103128c506b8Sjruoho ******************************************************************************/ 103228c506b8Sjruoho 103328c506b8Sjruoho void 103428c506b8Sjruoho RsDoResourceTemplate ( 103528c506b8Sjruoho ACPI_PARSE_OBJECT *Op) 103628c506b8Sjruoho { 103728c506b8Sjruoho ACPI_PARSE_OBJECT *BufferLengthOp; 103828c506b8Sjruoho ACPI_PARSE_OBJECT *BufferOp; 103928c506b8Sjruoho ACPI_PARSE_OBJECT *DescriptorTypeOp; 104028c506b8Sjruoho ACPI_PARSE_OBJECT *LastOp = NULL; 104128c506b8Sjruoho UINT32 CurrentByteOffset = 0; 104228c506b8Sjruoho ASL_RESOURCE_NODE HeadRnode; 104328c506b8Sjruoho ASL_RESOURCE_NODE *PreviousRnode; 104428c506b8Sjruoho ASL_RESOURCE_NODE *Rnode; 1045460301d4Schristos ASL_RESOURCE_INFO Info; 104628c506b8Sjruoho UINT8 State; 104728c506b8Sjruoho 104828c506b8Sjruoho 104928c506b8Sjruoho /* Mark parent as containing a resource template */ 105028c506b8Sjruoho 105128c506b8Sjruoho if (Op->Asl.Parent) 105228c506b8Sjruoho { 105389b8eb6cSchristos Op->Asl.Parent->Asl.CompileFlags |= OP_IS_RESOURCE_DESC; 105428c506b8Sjruoho } 105528c506b8Sjruoho 105628c506b8Sjruoho /* ResourceTemplate Opcode is first (Op) */ 105728c506b8Sjruoho /* Buffer Length node is first child */ 105828c506b8Sjruoho 105928c506b8Sjruoho BufferLengthOp = ASL_GET_CHILD_NODE (Op); 106028c506b8Sjruoho 106128c506b8Sjruoho /* Buffer Op is first peer */ 106228c506b8Sjruoho 106328c506b8Sjruoho BufferOp = ASL_GET_PEER_NODE (BufferLengthOp); 106428c506b8Sjruoho 106528c506b8Sjruoho /* First Descriptor type is next */ 106628c506b8Sjruoho 106728c506b8Sjruoho DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp); 106828c506b8Sjruoho 106989b8eb6cSchristos /* DEFAULT_ARG indicates null template - ResourceTemplate(){} */ 107089b8eb6cSchristos 107189b8eb6cSchristos if (DescriptorTypeOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 107289b8eb6cSchristos { 107389b8eb6cSchristos AslError (ASL_WARNING, ASL_MSG_NULL_RESOURCE_TEMPLATE, 107489b8eb6cSchristos DescriptorTypeOp, DescriptorTypeOp->Asl.Value.String); 107589b8eb6cSchristos } 107689b8eb6cSchristos 107728c506b8Sjruoho /* 107828c506b8Sjruoho * Process all resource descriptors in the list 107928c506b8Sjruoho * Note: It is assumed that the EndTag node has been automatically 108028c506b8Sjruoho * inserted at the end of the template by the parser. 108128c506b8Sjruoho */ 108228c506b8Sjruoho State = ACPI_RSTATE_NORMAL; 108328c506b8Sjruoho PreviousRnode = &HeadRnode; 108428c506b8Sjruoho while (DescriptorTypeOp) 108528c506b8Sjruoho { 1086460301d4Schristos /* Save information for optional mapfile */ 1087460301d4Schristos 1088460301d4Schristos if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION) 1089460301d4Schristos { 1090460301d4Schristos Info.MappingOp = Op->Asl.Parent; 1091460301d4Schristos } 1092460301d4Schristos else 1093460301d4Schristos { 1094460301d4Schristos Info.MappingOp = DescriptorTypeOp; 1095460301d4Schristos } 1096460301d4Schristos 1097460301d4Schristos Info.DescriptorTypeOp = DescriptorTypeOp; 1098460301d4Schristos Info.CurrentByteOffset = CurrentByteOffset; 1099460301d4Schristos 110089b8eb6cSchristos DescriptorTypeOp->Asl.CompileFlags |= OP_IS_RESOURCE_DESC; 1101460301d4Schristos Rnode = RsDoOneResourceDescriptor (&Info, &State); 110228c506b8Sjruoho 110328c506b8Sjruoho /* 110428c506b8Sjruoho * Update current byte offset to indicate the number of bytes from the 110528c506b8Sjruoho * start of the buffer. Buffer can include multiple descriptors, we 110628c506b8Sjruoho * must keep track of the offset of not only each descriptor, but each 110728c506b8Sjruoho * element (field) within each descriptor as well. 110828c506b8Sjruoho */ 110928c506b8Sjruoho CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode); 111028c506b8Sjruoho 111128c506b8Sjruoho /* Get the next descriptor in the list */ 111228c506b8Sjruoho 111328c506b8Sjruoho LastOp = DescriptorTypeOp; 111428c506b8Sjruoho DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp); 111528c506b8Sjruoho } 111628c506b8Sjruoho 111728c506b8Sjruoho if (State == ACPI_RSTATE_DEPENDENT_LIST) 111828c506b8Sjruoho { 111928c506b8Sjruoho if (LastOp) 112028c506b8Sjruoho { 112128c506b8Sjruoho LastOp = LastOp->Asl.Parent; 112228c506b8Sjruoho } 112328c506b8Sjruoho AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL); 112428c506b8Sjruoho } 112528c506b8Sjruoho 112628c506b8Sjruoho /* 112728c506b8Sjruoho * Transform the nodes into the following 112828c506b8Sjruoho * 112928c506b8Sjruoho * Op -> AML_BUFFER_OP 113028c506b8Sjruoho * First Child -> BufferLength 113128c506b8Sjruoho * Second Child -> Descriptor Buffer (raw byte data) 113228c506b8Sjruoho */ 113328c506b8Sjruoho Op->Asl.ParseOpcode = PARSEOP_BUFFER; 113428c506b8Sjruoho Op->Asl.AmlOpcode = AML_BUFFER_OP; 113589b8eb6cSchristos Op->Asl.CompileFlags = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC; 1136ff4a156dSchristos UtSetParseOpName (Op); 113728c506b8Sjruoho 113828c506b8Sjruoho BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; 113928c506b8Sjruoho BufferLengthOp->Asl.Value.Integer = CurrentByteOffset; 114028c506b8Sjruoho (void) OpcSetOptimalIntegerSize (BufferLengthOp); 1141ff4a156dSchristos UtSetParseOpName (BufferLengthOp); 114228c506b8Sjruoho 114328c506b8Sjruoho BufferOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 114428c506b8Sjruoho BufferOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN; 114528c506b8Sjruoho BufferOp->Asl.AmlOpcodeLength = 0; 114628c506b8Sjruoho BufferOp->Asl.AmlLength = CurrentByteOffset; 114732aedd46Schristos BufferOp->Asl.Value.Buffer = ACPI_CAST_PTR (UINT8, HeadRnode.Next); 114889b8eb6cSchristos BufferOp->Asl.CompileFlags |= OP_IS_RESOURCE_DATA; 1149ff4a156dSchristos UtSetParseOpName (BufferOp); 115028c506b8Sjruoho 115128c506b8Sjruoho return; 115228c506b8Sjruoho } 1153