Path: blob/main/sys/contrib/dev/acpica/components/dispatcher/dspkginit.c
48521 views
/******************************************************************************1*2* Module Name: dspkginit - Completion of deferred package initialization3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/acnamesp.h>154#include <contrib/dev/acpica/include/amlcode.h>155#include <contrib/dev/acpica/include/acdispat.h>156#include <contrib/dev/acpica/include/acinterp.h>157#include <contrib/dev/acpica/include/acparser.h>158159160#define _COMPONENT ACPI_NAMESPACE161ACPI_MODULE_NAME ("dspkginit")162163164/* Local prototypes */165166static void167AcpiDsResolvePackageElement (168ACPI_OPERAND_OBJECT **Element);169170171/*******************************************************************************172*173* FUNCTION: AcpiDsBuildInternalPackageObj174*175* PARAMETERS: WalkState - Current walk state176* Op - Parser object to be translated177* ElementCount - Number of elements in the package - this is178* the NumElements argument to Package()179* ObjDescPtr - Where the ACPI internal object is returned180*181* RETURN: Status182*183* DESCRIPTION: Translate a parser Op package object to the equivalent184* namespace object185*186* NOTE: The number of elements in the package will be always be the NumElements187* count, regardless of the number of elements in the package list. If188* NumElements is smaller, only that many package list elements are used.189* if NumElements is larger, the Package object is padded out with190* objects of type Uninitialized (as per ACPI spec.)191*192* Even though the ASL compilers do not allow NumElements to be smaller193* than the Package list length (for the fixed length package opcode), some194* BIOS code modifies the AML on the fly to adjust the NumElements, and195* this code compensates for that. This also provides compatibility with196* other AML interpreters.197*198******************************************************************************/199200ACPI_STATUS201AcpiDsBuildInternalPackageObj (202ACPI_WALK_STATE *WalkState,203ACPI_PARSE_OBJECT *Op,204UINT32 ElementCount,205ACPI_OPERAND_OBJECT **ObjDescPtr)206{207ACPI_PARSE_OBJECT *Arg;208ACPI_PARSE_OBJECT *Parent;209ACPI_OPERAND_OBJECT *ObjDesc = NULL;210ACPI_STATUS Status = AE_OK;211BOOLEAN ModuleLevelCode = FALSE;212UINT16 ReferenceCount;213UINT32 Index;214UINT32 i;215216217ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj);218219220/* Check if we are executing module level code */221222if (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)223{224ModuleLevelCode = TRUE;225}226227/* Find the parent of a possibly nested package */228229Parent = Op->Common.Parent;230while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||231(Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))232{233Parent = Parent->Common.Parent;234}235236/*237* If we are evaluating a Named package object of the form:238* Name (xxxx, Package)239* the package object already exists, otherwise it must be created.240*/241ObjDesc = *ObjDescPtr;242if (!ObjDesc)243{244ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE);245*ObjDescPtr = ObjDesc;246if (!ObjDesc)247{248return_ACPI_STATUS (AE_NO_MEMORY);249}250251ObjDesc->Package.Node = Parent->Common.Node;252}253254if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID) /* Just in case */255{256return_ACPI_STATUS (AE_OK);257}258259/*260* Allocate the element array (array of pointers to the individual261* objects) if necessary. the count is based on the NumElements262* parameter. Add an extra pointer slot so that the list is always263* null terminated.264*/265if (!ObjDesc->Package.Elements)266{267ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED (268((ACPI_SIZE) ElementCount + 1) * sizeof (void *));269270if (!ObjDesc->Package.Elements)271{272AcpiUtDeleteObjectDesc (ObjDesc);273return_ACPI_STATUS (AE_NO_MEMORY);274}275276ObjDesc->Package.Count = ElementCount;277}278279/* First arg is element count. Second arg begins the initializer list */280281Arg = Op->Common.Value.Arg;282Arg = Arg->Common.Next;283284/*285* If we are executing module-level code, we will defer the286* full resolution of the package elements in order to support287* forward references from the elements. This provides288* compatibility with other ACPI implementations.289*/290if (ModuleLevelCode)291{292ObjDesc->Package.AmlStart = WalkState->Aml;293ObjDesc->Package.AmlLength = 0;294295ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,296"%s: Deferring resolution of Package elements\n",297ACPI_GET_FUNCTION_NAME));298}299300/*301* Initialize the elements of the package, up to the NumElements count.302* Package is automatically padded with uninitialized (NULL) elements303* if NumElements is greater than the package list length. Likewise,304* Package is truncated if NumElements is less than the list length.305*/306for (i = 0; Arg && (i < ElementCount); i++)307{308if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP)309{310if (!Arg->Common.Node)311{312/*313* This is the case where an expression has returned a value.314* The use of expressions (TermArgs) within individual315* package elements is not supported by the AML interpreter,316* even though the ASL grammar supports it. Example:317*318* Name (INT1, 0x1234)319*320* Name (PKG3, Package () {321* Add (INT1, 0xAAAA0000)322* })323*324* 1) No known AML interpreter supports this type of construct325* 2) This fixes a fault if the construct is encountered326*/327ACPI_EXCEPTION ((AE_INFO, AE_SUPPORT,328"Expressions within package elements are not supported"));329330/* Cleanup the return object, it is not needed */331332AcpiUtRemoveReference (WalkState->Results->Results.ObjDesc[0]);333return_ACPI_STATUS (AE_SUPPORT);334}335336if (Arg->Common.Node->Type == ACPI_TYPE_METHOD)337{338/*339* A method reference "looks" to the parser to be a method340* invocation, so we special case it here341*/342Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP;343Status = AcpiDsBuildInternalObject (344WalkState, Arg, &ObjDesc->Package.Elements[i]);345}346else347{348/* This package element is already built, just get it */349350ObjDesc->Package.Elements[i] =351ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node);352}353}354else355{356Status = AcpiDsBuildInternalObject (357WalkState, Arg, &ObjDesc->Package.Elements[i]);358if (Status == AE_NOT_FOUND)359{360ACPI_ERROR ((AE_INFO, "%-48s", "****DS namepath not found"));361}362363if (!ModuleLevelCode)364{365/*366* Initialize this package element. This function handles the367* resolution of named references within the package.368* Forward references from module-level code are deferred369* until all ACPI tables are loaded.370*/371AcpiDsInitPackageElement (0, ObjDesc->Package.Elements[i],372NULL, &ObjDesc->Package.Elements[i]);373}374}375376if (*ObjDescPtr)377{378/* Existing package, get existing reference count */379380ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount;381if (ReferenceCount > 1)382{383/* Make new element ref count match original ref count */384/* TBD: Probably need an AcpiUtAddReferences function */385386for (Index = 0; Index < ((UINT32) ReferenceCount - 1); Index++)387{388AcpiUtAddReference ((ObjDesc->Package.Elements[i]));389}390}391}392393Arg = Arg->Common.Next;394}395396/* Check for match between NumElements and actual length of PackageList */397398if (Arg)399{400/*401* NumElements was exhausted, but there are remaining elements in402* the PackageList. Truncate the package to NumElements.403*404* Note: technically, this is an error, from ACPI spec: "It is an405* error for NumElements to be less than the number of elements in406* the PackageList". However, we just print a message and no407* exception is returned. This provides compatibility with other408* ACPI implementations. Some firmware implementations will alter409* the NumElements on the fly, possibly creating this type of410* ill-formed package object.411*/412while (Arg)413{414/*415* We must delete any package elements that were created earlier416* and are not going to be used because of the package truncation.417*/418if (Arg->Common.Node)419{420AcpiUtRemoveReference (421ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node));422Arg->Common.Node = NULL;423}424425/* Find out how many elements there really are */426427i++;428Arg = Arg->Common.Next;429}430431ACPI_INFO ((432"Actual Package length (%u) is larger than "433"NumElements field (%u), truncated",434i, ElementCount));435}436else if (i < ElementCount)437{438/*439* Arg list (elements) was exhausted, but we did not reach440* NumElements count.441*442* Note: this is not an error, the package is padded out443* with NULLs as per the ACPI specification.444*/445ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,446"%s: Package List length (%u) smaller than NumElements "447"count (%u), padded with null elements\n",448ACPI_GET_FUNCTION_NAME, i, ElementCount));449}450451/* Module-level packages will be resolved later */452453if (!ModuleLevelCode)454{455ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;456}457458Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);459return_ACPI_STATUS (Status);460}461462463/*******************************************************************************464*465* FUNCTION: AcpiDsInitPackageElement466*467* PARAMETERS: ACPI_PKG_CALLBACK468*469* RETURN: Status470*471* DESCRIPTION: Resolve a named reference element within a package object472*473******************************************************************************/474475ACPI_STATUS476AcpiDsInitPackageElement (477UINT8 ObjectType,478ACPI_OPERAND_OBJECT *SourceObject,479ACPI_GENERIC_STATE *State,480void *Context)481{482ACPI_OPERAND_OBJECT **ElementPtr;483484485ACPI_FUNCTION_TRACE (DsInitPackageElement);486487488if (!SourceObject)489{490return_ACPI_STATUS (AE_OK);491}492493/*494* The following code is a bit of a hack to workaround a (current)495* limitation of the ACPI_PKG_CALLBACK interface. We need a pointer496* to the location within the element array because a new object497* may be created and stored there.498*/499if (Context)500{501/* A direct call was made to this function */502503ElementPtr = (ACPI_OPERAND_OBJECT **) Context;504}505else506{507/* Call came from AcpiUtWalkPackageTree */508509ElementPtr = State->Pkg.ThisTargetObj;510}511512/* We are only interested in reference objects/elements */513514if (SourceObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)515{516/* Attempt to resolve the (named) reference to a namespace node */517518AcpiDsResolvePackageElement (ElementPtr);519}520else if (SourceObject->Common.Type == ACPI_TYPE_PACKAGE)521{522SourceObject->Package.Flags |= AOPOBJ_DATA_VALID;523}524525return_ACPI_STATUS (AE_OK);526}527528529/*******************************************************************************530*531* FUNCTION: AcpiDsResolvePackageElement532*533* PARAMETERS: ElementPtr - Pointer to a reference object534*535* RETURN: Possible new element is stored to the indirect ElementPtr536*537* DESCRIPTION: Resolve a package element that is a reference to a named538* object.539*540******************************************************************************/541542static void543AcpiDsResolvePackageElement (544ACPI_OPERAND_OBJECT **ElementPtr)545{546ACPI_STATUS Status;547ACPI_STATUS Status2;548ACPI_GENERIC_STATE ScopeInfo;549ACPI_OPERAND_OBJECT *Element = *ElementPtr;550ACPI_NAMESPACE_NODE *ResolvedNode;551ACPI_NAMESPACE_NODE *OriginalNode;552char *ExternalPath = "";553ACPI_OBJECT_TYPE Type;554555556ACPI_FUNCTION_TRACE (DsResolvePackageElement);557558559/* Check if reference element is already resolved */560561if (Element->Reference.Resolved)562{563ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,564"%s: Package element is already resolved\n",565ACPI_GET_FUNCTION_NAME));566567return_VOID;568}569570/* Element must be a reference object of correct type */571572ScopeInfo.Scope.Node = Element->Reference.Node; /* Prefix node */573574Status = AcpiNsLookup (&ScopeInfo, (char *) Element->Reference.Aml,575ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,576ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,577NULL, &ResolvedNode);578if (ACPI_FAILURE (Status))579{580if ((Status == AE_NOT_FOUND) && AcpiGbl_IgnorePackageResolutionErrors)581{582/*583* Optionally be silent about the NOT_FOUND case for the referenced584* name. Although this is potentially a serious problem,585* it can generate a lot of noise/errors on platforms whose586* firmware carries around a bunch of unused Package objects.587* To disable these errors, set this global to TRUE:588* AcpiGbl_IgnorePackageResolutionErrors589*590* If the AML actually tries to use such a package, the unresolved591* element(s) will be replaced with NULL elements.592*/593594/* Referenced name not found, set the element to NULL */595596AcpiUtRemoveReference (*ElementPtr);597*ElementPtr = NULL;598return_VOID;599}600601Status2 = AcpiNsExternalizeName (ACPI_UINT32_MAX,602(char *) Element->Reference.Aml, NULL, &ExternalPath);603604ACPI_EXCEPTION ((AE_INFO, Status,605"While resolving a named reference package element - %s",606ExternalPath));607if (ACPI_SUCCESS (Status2))608{609ACPI_FREE (ExternalPath);610}611612/* Could not resolve name, set the element to NULL */613614AcpiUtRemoveReference (*ElementPtr);615*ElementPtr = NULL;616return_VOID;617}618else if (ResolvedNode->Type == ACPI_TYPE_ANY)619{620/* Named reference not resolved, return a NULL package element */621622ACPI_ERROR ((AE_INFO,623"Could not resolve named package element [%4.4s] in [%4.4s]",624ResolvedNode->Name.Ascii, ScopeInfo.Scope.Node->Name.Ascii));625*ElementPtr = NULL;626return_VOID;627}628629/*630* Special handling for Alias objects. We need ResolvedNode to point631* to the Alias target. This effectively "resolves" the alias.632*/633if (ResolvedNode->Type == ACPI_TYPE_LOCAL_ALIAS)634{635ResolvedNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,636ResolvedNode->Object);637}638639/* Update the reference object */640641Element->Reference.Resolved = TRUE;642Element->Reference.Node = ResolvedNode;643Type = Element->Reference.Node->Type;644645/*646* Attempt to resolve the node to a value before we insert it into647* the package. If this is a reference to a common data type,648* resolve it immediately. According to the ACPI spec, package649* elements can only be "data objects" or method references.650* Attempt to resolve to an Integer, Buffer, String or Package.651* If cannot, return the named reference (for things like Devices,652* Methods, etc.) Buffer Fields and Fields will resolve to simple653* objects (int/buf/str/pkg).654*655* NOTE: References to things like Devices, Methods, Mutexes, etc.656* will remain as named references. This behavior is not described657* in the ACPI spec, but it appears to be an oversight.658*/659OriginalNode = ResolvedNode;660Status = AcpiExResolveNodeToValue (&ResolvedNode, NULL);661if (ACPI_FAILURE (Status))662{663return_VOID;664}665666switch (Type)667{668/*669* These object types are a result of named references, so we will670* leave them as reference objects. In other words, these types671* have no intrinsic "value".672*/673case ACPI_TYPE_DEVICE:674case ACPI_TYPE_THERMAL:675case ACPI_TYPE_METHOD:676break;677678case ACPI_TYPE_MUTEX:679case ACPI_TYPE_POWER:680case ACPI_TYPE_PROCESSOR:681case ACPI_TYPE_EVENT:682case ACPI_TYPE_REGION:683684/* AcpiExResolveNodeToValue gave these an extra reference */685686AcpiUtRemoveReference (OriginalNode->Object);687break;688689default:690/*691* For all other types - the node was resolved to an actual692* operand object with a value, return the object. Remove693* a reference on the existing object.694*/695AcpiUtRemoveReference (Element);696*ElementPtr = (ACPI_OPERAND_OBJECT *) ResolvedNode;697break;698}699700return_VOID;701}702703704