Path: blob/main/sys/contrib/dev/acpica/compiler/asloperands.c
48373 views
/******************************************************************************1*2* Module Name: asloperands - AML operand processing3*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/compiler/aslcompiler.h>152#include "aslcompiler.y.h"153#include <contrib/dev/acpica/include/amlcode.h>154155#define _COMPONENT ACPI_COMPILER156ACPI_MODULE_NAME ("asloperands")157158/* Local prototypes */159160static void161OpnDoField (162ACPI_PARSE_OBJECT *Op);163164static void165OpnDoBankField (166ACPI_PARSE_OBJECT *Op);167168static void169OpnDoBuffer (170ACPI_PARSE_OBJECT *Op);171172static void173OpnDoDefinitionBlock (174ACPI_PARSE_OBJECT *Op);175176static void177OpnDoFieldCommon (178ACPI_PARSE_OBJECT *FieldOp,179ACPI_PARSE_OBJECT *Op);180181static void182OpnDoIndexField (183ACPI_PARSE_OBJECT *Op);184185static void186OpnDoLoadTable (187ACPI_PARSE_OBJECT *Op);188189static void190OpnDoMethod (191ACPI_PARSE_OBJECT *Op);192193static void194OpnDoMutex (195ACPI_PARSE_OBJECT *Op);196197static void198OpnDoRegion (199ACPI_PARSE_OBJECT *Op);200201static void202OpnAttachNameToNode (203ACPI_PARSE_OBJECT *Op);204205206/*******************************************************************************207*208* FUNCTION: OpnDoMutex209*210* PARAMETERS: Op - The parent parse node211*212* RETURN: None213*214* DESCRIPTION: Construct the operands for the MUTEX ASL keyword.215*216******************************************************************************/217218static void219OpnDoMutex (220ACPI_PARSE_OBJECT *Op)221{222ACPI_PARSE_OBJECT *Next;223224225Next = Op->Asl.Child;226Next = Next->Asl.Next;227228if (Next->Asl.Value.Integer > 15)229{230AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);231}232return;233}234235236/*******************************************************************************237*238* FUNCTION: OpnDoMethod239*240* PARAMETERS: Op - The parent parse node241*242* RETURN: None243*244* DESCRIPTION: Construct the operands for the METHOD ASL keyword.245*246******************************************************************************/247248static void249OpnDoMethod (250ACPI_PARSE_OBJECT *Op)251{252ACPI_PARSE_OBJECT *Next;253254/* Optional arguments for this opcode with defaults */255256UINT8 NumArgs = 0;257UINT8 Serialized = 0;258UINT8 Concurrency = 0;259UINT8 MethodFlags;260261262/* Opcode and package length first */263/* Method name */264265Next = Op->Asl.Child;266267/* Num args */268269Next = Next->Asl.Next;270if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)271{272NumArgs = (UINT8) Next->Asl.Value.Integer;273Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;274}275276/* Serialized Flag */277278Next = Next->Asl.Next;279if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)280{281Serialized = (UINT8) Next->Asl.Value.Integer;282Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;283}284285/* Concurrency value (valid values are 0-15) */286287Next = Next->Asl.Next;288if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)289{290/* This is a ByteConstExpr, so eval the constant now */291292OpcAmlConstantWalk (Next, 0, NULL);293294if (Next->Asl.Value.Integer > 15)295{296AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);297}298299Concurrency = (UINT8) Next->Asl.Value.Integer;300}301302/* Put the bits in their proper places */303304MethodFlags = (UINT8)305((NumArgs & 0x7) |306((Serialized & 0x1) << 3) |307((Concurrency & 0xF) << 4));308309/* Use the last node for the combined flags byte */310311Next->Asl.Value.Integer = MethodFlags;312Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;313Next->Asl.AmlLength = 1;314Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;315316/* Save the arg count in the first node */317318Op->Asl.Extra = NumArgs;319}320321322/*******************************************************************************323*324* FUNCTION: OpnDoFieldCommon325*326* PARAMETERS: FieldOp - Node for an ASL field327* Op - The parent parse node328*329* RETURN: None330*331* DESCRIPTION: Construct the AML operands for the various field keywords,332* FIELD, BANKFIELD, INDEXFIELD333*334******************************************************************************/335336static void337OpnDoFieldCommon (338ACPI_PARSE_OBJECT *FieldOp,339ACPI_PARSE_OBJECT *Op)340{341ACPI_PARSE_OBJECT *Next;342ACPI_PARSE_OBJECT *PkgLengthNode;343UINT32 CurrentBitOffset;344UINT32 NewBitOffset;345UINT8 AccessType;346UINT8 LockRule;347UINT8 UpdateRule;348UINT8 FieldFlags;349UINT32 MinimumLength;350351352/* AccessType -- not optional, so no need to check for DEFAULT_ARG */353354AccessType = (UINT8) Op->Asl.Value.Integer;355Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;356357/* Set the access type in the parent (field) node for use later */358359FieldOp->Asl.Value.Integer = AccessType;360361/* LockRule -- not optional, so no need to check for DEFAULT_ARG */362363Next = Op->Asl.Next;364LockRule = (UINT8) Next->Asl.Value.Integer;365Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;366367/* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */368369Next = Next->Asl.Next;370UpdateRule = (UINT8) Next->Asl.Value.Integer;371372/*373* Generate the flags byte. The various fields are already374* in the right bit position via translation from the375* keywords by the parser.376*/377FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);378379/* Use the previous node to be the FieldFlags node */380381/* Set the node to RAW_DATA */382383Next->Asl.Value.Integer = FieldFlags;384Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;385Next->Asl.AmlLength = 1;386Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;387388/* Process the FieldUnitList */389390Next = Next->Asl.Next;391CurrentBitOffset = 0;392393while (Next)394{395/* Save the offset of this field unit */396397Next->Asl.ExtraValue = CurrentBitOffset;398399switch (Next->Asl.ParseOpcode)400{401case PARSEOP_ACCESSAS:402403PkgLengthNode = Next->Asl.Child;404AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;405406/* Nothing additional to do */407break;408409case PARSEOP_OFFSET:410411/* New offset into the field */412413PkgLengthNode = Next->Asl.Child;414NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;415416/*417* Examine the specified offset in relation to the418* current offset counter.419*/420if (NewBitOffset < CurrentBitOffset)421{422/*423* Not allowed to specify a backwards offset!424* Issue error and ignore this node.425*/426AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,427NULL);428Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;429PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;430}431#ifdef _OBSOLETE_CODE432/*433* January 2022: removed this check due to complaints by users434* for too many (invalid) remarks.435*/436else if (NewBitOffset == CurrentBitOffset)437{438/*439* This Offset() operator is redundant and not needed,440* because the offset value is the same as the current441* offset.442*/443AslError (ASL_REMARK, ASL_MSG_OFFSET, PkgLengthNode, NULL);444445if (AslGbl_OptimizeTrivialParseNodes)446{447/*448* Optimize this Offset() operator by removing/ignoring449* it. Set the related nodes to default.450*/451Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;452PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;453454AslError (ASL_OPTIMIZATION, ASL_MSG_OFFSET, PkgLengthNode,455"Optimizer has removed statement");456}457else458{459/* Optimization is disabled, treat as a valid Offset */460461PkgLengthNode->Asl.Value.Integer =462NewBitOffset - CurrentBitOffset;463CurrentBitOffset = NewBitOffset;464}465}466#endif467else468{469/*470* Valid new offset - set the value to be inserted into the AML471* and update the offset counter.472*/473PkgLengthNode->Asl.Value.Integer =474NewBitOffset - CurrentBitOffset;475CurrentBitOffset = NewBitOffset;476}477break;478479case PARSEOP_NAMESEG:480case PARSEOP_RESERVED_BYTES:481482/* Named or reserved field entry */483484PkgLengthNode = Next->Asl.Child;485NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer;486CurrentBitOffset += NewBitOffset;487488if ((NewBitOffset == 0) &&489(Next->Asl.ParseOpcode == PARSEOP_RESERVED_BYTES) &&490AslGbl_OptimizeTrivialParseNodes)491{492/*493* Unnamed field with a bit length of zero. We can494* safely just ignore this. However, we will not ignore495* a named field of zero length, we don't want to just496* toss out a name.497*/498Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;499PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;500break;501}502503/* Save the current AccessAs value for error checking later */504505switch (AccessType)506{507case AML_FIELD_ACCESS_ANY:508case AML_FIELD_ACCESS_BYTE:509case AML_FIELD_ACCESS_BUFFER:510default:511512MinimumLength = 8;513break;514515case AML_FIELD_ACCESS_WORD:516MinimumLength = 16;517break;518519case AML_FIELD_ACCESS_DWORD:520MinimumLength = 32;521break;522523case AML_FIELD_ACCESS_QWORD:524MinimumLength = 64;525break;526}527528PkgLengthNode->Asl.ExtraValue = MinimumLength;529break;530531default:532533/* All supported field opcodes must appear above */534535break;536}537538/* Move on to next entry in the field list */539540Next = Next->Asl.Next;541}542}543544545/*******************************************************************************546*547* FUNCTION: OpnDoField548*549* PARAMETERS: Op - The parent parse node550*551* RETURN: None552*553* DESCRIPTION: Construct the AML operands for the FIELD ASL keyword554*555******************************************************************************/556557static void558OpnDoField (559ACPI_PARSE_OBJECT *Op)560{561ACPI_PARSE_OBJECT *Next;562563564/* Opcode is parent node */565/* First child is field name */566567Next = Op->Asl.Child;568569/* Second child is the AccessType */570571OpnDoFieldCommon (Op, Next->Asl.Next);572}573574575/*******************************************************************************576*577* FUNCTION: OpnDoIndexField578*579* PARAMETERS: Op - The parent parse node580*581* RETURN: None582*583* DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword584*585******************************************************************************/586587static void588OpnDoIndexField (589ACPI_PARSE_OBJECT *Op)590{591ACPI_PARSE_OBJECT *Next;592593594/* Opcode is parent node */595/* First child is the index name */596597Next = Op->Asl.Child;598599/* Second child is the data name */600601Next = Next->Asl.Next;602603/* Third child is the AccessType */604605OpnDoFieldCommon (Op, Next->Asl.Next);606}607608609/*******************************************************************************610*611* FUNCTION: OpnDoBankField612*613* PARAMETERS: Op - The parent parse node614*615* RETURN: None616*617* DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword618*619******************************************************************************/620621static void622OpnDoBankField (623ACPI_PARSE_OBJECT *Op)624{625ACPI_PARSE_OBJECT *Next;626627628/* Opcode is parent node */629/* First child is the region name */630631Next = Op->Asl.Child;632633/* Second child is the bank name */634635Next = Next->Asl.Next;636637/* Third child is the bank value */638639Next = Next->Asl.Next;640641/* Fourth child is the AccessType */642643OpnDoFieldCommon (Op, Next->Asl.Next);644}645646647/*******************************************************************************648*649* FUNCTION: OpnDoRegion650*651* PARAMETERS: Op - The parent parse node652*653* RETURN: None654*655* DESCRIPTION: Tries to get the length of the region. Can only do this at656* compile time if the length is a constant.657*658******************************************************************************/659660static void661OpnDoRegion (662ACPI_PARSE_OBJECT *Op)663{664ACPI_PARSE_OBJECT *Next;665ACPI_ADR_SPACE_TYPE SpaceId;666667668/* Opcode is parent node */669/* First child is the region name */670671Next = Op->Asl.Child;672673/* Second child is the space ID */674675Next = Next->Asl.Next;676SpaceId = (ACPI_ADR_SPACE_TYPE) Next->Common.Value.Integer;677678/* Third child is the region offset */679680Next = Next->Asl.Next;681682/* Fourth child is the region length */683684Next = Next->Asl.Next;685if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)686{687/* Check for zero length */688689Op->Asl.Value.Integer = Next->Asl.Value.Integer;690if (!Op->Asl.Value.Integer && (SpaceId < ACPI_NUM_PREDEFINED_REGIONS))691{692AslError (ASL_ERROR, ASL_MSG_REGION_LENGTH, Op, NULL);693}694}695else696{697Op->Asl.Value.Integer = ACPI_UINT64_MAX;698}699}700701702/*******************************************************************************703*704* FUNCTION: OpnDoBuffer705*706* PARAMETERS: Op - The parent parse node707*708* RETURN: None709*710* DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We711* build a single raw byte buffer from the initialization nodes,712* each parse node contains a buffer byte.713*714******************************************************************************/715716static void717OpnDoBuffer (718ACPI_PARSE_OBJECT *Op)719{720ACPI_PARSE_OBJECT *InitializerOp;721ACPI_PARSE_OBJECT *BufferLengthOp;722723/* Optional arguments for this opcode with defaults */724725UINT32 BufferLength = 0;726727728/* Opcode and package length first */729/* Buffer Length is next, followed by the initializer list */730731BufferLengthOp = Op->Asl.Child;732InitializerOp = BufferLengthOp->Asl.Next;733734/*735* If the BufferLength is not an INTEGER or was not specified in the ASL736* (DEFAULT_ARG), it is a TermArg that is737* evaluated at run-time, and we are therefore finished.738*/739if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&740(BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))741{742return;743}744745/*746* We want to count the number of items in the initializer list, because if747* it is larger than the buffer length, we will define the buffer size748* to be the size of the initializer list (as per the ACPI Specification)749*/750switch (InitializerOp->Asl.ParseOpcode)751{752case PARSEOP_INTEGER:753case PARSEOP_BYTECONST:754case PARSEOP_WORDCONST:755case PARSEOP_DWORDCONST:756757/* The peer list contains the byte list (if any...) */758759while (InitializerOp)760{761/* For buffers, this is a list of raw bytes */762763InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;764InitializerOp->Asl.AmlLength = 1;765InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;766767BufferLength++;768InitializerOp = ASL_GET_PEER_NODE (InitializerOp);769}770break;771772case PARSEOP_STRING_LITERAL:773774/*775* Only one initializer, the string. Buffer must be big enough to hold776* the string plus the null termination byte777*/778BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;779780InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;781InitializerOp->Asl.AmlLength = BufferLength;782InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;783break;784785case PARSEOP_RAW_DATA:786787/* Buffer nodes are already initialized (e.g. Unicode operator) */788return;789790case PARSEOP_DEFAULT_ARG:791break;792793default:794795AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,796"Unknown buffer initializer opcode");797printf ("Unknown buffer initializer opcode [%s]\n",798UtGetOpName (InitializerOp->Asl.ParseOpcode));799return;800}801802/* Check if initializer list is longer than the buffer length */803804if (BufferLengthOp->Asl.Value.Integer > BufferLength)805{806BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;807}808809if (!BufferLength)810{811/* No length AND no items -- issue notice */812813AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);814815/* But go ahead and put the buffer length of zero into the AML */816}817818/*819* Just set the buffer size node to be the buffer length, regardless820* of whether it was previously an integer or a default_arg placeholder821*/822BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;823BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;824BufferLengthOp->Asl.Value.Integer = BufferLength;825826(void) OpcSetOptimalIntegerSize (BufferLengthOp);827UtSetParseOpName (BufferLengthOp);828829/* Remaining nodes are handled via the tree walk */830}831832833/*******************************************************************************834*835* FUNCTION: OpnDoPackage836*837* PARAMETERS: Op - The parent parse node838*839* RETURN: None840*841* DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:842* can only be called after constants have been folded, to ensure843* that the PackageLength operand has been fully reduced.844*845******************************************************************************/846847void848OpnDoPackage (849ACPI_PARSE_OBJECT *Op)850{851ACPI_PARSE_OBJECT *InitializerOp;852ACPI_PARSE_OBJECT *PackageLengthOp;853UINT32 PackageLength = 0;854855856/* Opcode and package length first, followed by the initializer list */857858PackageLengthOp = Op->Asl.Child;859InitializerOp = PackageLengthOp->Asl.Next;860861/* Count the number of items in the initializer list */862863if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)864{865/* The peer list contains the byte list (if any...) */866867while (InitializerOp)868{869PackageLength++;870InitializerOp = InitializerOp->Asl.Next;871}872}873874/* If package length is a constant, compare to the initializer list */875876if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||877(PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))878{879if (PackageLengthOp->Asl.Value.Integer > PackageLength)880{881/*882* Allow package length to be longer than the initializer883* list -- but if the length of initializer list is nonzero,884* issue a message since this is probably a coding error,885* even though technically legal.886*/887if (PackageLength > 0)888{889AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,890PackageLengthOp, NULL);891}892893PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;894}895else if (PackageLengthOp->Asl.Value.Integer < PackageLength)896{897/*898* The package length is smaller than the length of the899* initializer list. This is an error as per the ACPI spec.900*/901AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,902PackageLengthOp, NULL);903}904}905906if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)907{908/*909* This is the case if the PackageLength was left empty - Package()910* The package length becomes the length of the initializer list911*/912Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;913Op->Asl.Child->Asl.Value.Integer = PackageLength;914UtSetParseOpName (Op);915916/* Set the AML opcode */917918(void) OpcSetOptimalIntegerSize (Op->Asl.Child);919}920921/* If not a variable-length package, check for a zero package length */922923if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||924(PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST) ||925(PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO) ||926(PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))927{928if (!PackageLength)929{930/* No length AND no initializer list -- issue a remark */931932AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,933PackageLengthOp, NULL);934935/* But go ahead and put the buffer length of zero into the AML */936}937}938939/*940* If the PackageLength is a constant <= 255, we can change the941* AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.942*/943if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&944(Op->Asl.Child->Asl.Value.Integer <= 255)) ||945(Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||946(Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||947(Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))948{949Op->Asl.AmlOpcode = AML_PACKAGE_OP;950Op->Asl.ParseOpcode = PARSEOP_PACKAGE;951952/*953* Just set the package size node to be the package length, regardless954* of whether it was previously an integer or a default_arg placeholder955*/956PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;957PackageLengthOp->Asl.AmlLength = 1;958PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;959PackageLengthOp->Asl.Value.Integer = PackageLength;960}961962/* Remaining nodes are handled via the tree walk */963}964965966/*******************************************************************************967*968* FUNCTION: OpnDoLoadTable969*970* PARAMETERS: Op - The parent parse node971*972* RETURN: None973*974* DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.975*976******************************************************************************/977978static void979OpnDoLoadTable (980ACPI_PARSE_OBJECT *Op)981{982ACPI_PARSE_OBJECT *Next;983984985/* Opcode is parent node */986/* First child is the table signature */987988Next = Op->Asl.Child;989990/* Second child is the OEM ID*/991992Next = Next->Asl.Next;993994/* Third child is the OEM table ID */995996Next = Next->Asl.Next;997998/* Fourth child is the RootPath string */9991000Next = Next->Asl.Next;1001if (Next->Asl.ParseOpcode == PARSEOP_ZERO)1002{1003Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;1004Next->Asl.Value.String = "\\";1005Next->Asl.AmlLength = 2;1006OpcGenerateAmlOpcode (Next);1007}10081009#ifdef ASL_FUTURE_IMPLEMENTATION10101011/* TBD: NOT IMPLEMENTED */1012/* Fifth child is the [optional] ParameterPathString */1013/* Sixth child is the [optional] ParameterData */10141015Next = Next->Asl.Next;1016if (Next->Asl.ParseOpcode == DEFAULT_ARG)1017{1018Next->Asl.AmlLength = 1;1019Next->Asl.ParseOpcode = ZERO;1020OpcGenerateAmlOpcode (Next);1021}102210231024Next = Next->Asl.Next;1025if (Next->Asl.ParseOpcode == DEFAULT_ARG)1026{1027Next->Asl.AmlLength = 1;1028Next->Asl.ParseOpcode = ZERO;1029OpcGenerateAmlOpcode (Next);1030}1031#endif1032}103310341035/*******************************************************************************1036*1037* FUNCTION: OpnDoDefinitionBlock1038*1039* PARAMETERS: Op - The parent parse node1040*1041* RETURN: None1042*1043* DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword1044*1045******************************************************************************/10461047static void1048OpnDoDefinitionBlock (1049ACPI_PARSE_OBJECT *Op)1050{1051ACPI_PARSE_OBJECT *Child;1052ACPI_SIZE Length;1053UINT32 i;1054char *Filename;1055ACPI_STATUS Status;105610571058/*1059* These nodes get stuffed into the table header. They are special1060* cased when the table is written to the output file.1061*1062* Mark all of these nodes as non-usable so they won't get output1063* as AML opcodes!1064*/10651066/* Get AML filename. Use it if non-null */10671068Child = Op->Asl.Child;1069if (Child->Asl.Value.Buffer &&1070*Child->Asl.Value.Buffer &&1071(AslGbl_UseDefaultAmlFilename))1072{1073/*1074* The walk may traverse multiple definition blocks. Switch files1075* to ensure that the correct files are manipulated.1076*/1077FlSwitchFileSet (Op->Asl.Filename);10781079/*1080* We will use the AML filename that is embedded in the source file1081* for the output filename.1082*/1083Filename = UtLocalCacheCalloc (strlen (AslGbl_DirectoryPath) +1084strlen ((char *) Child->Asl.Value.Buffer) + 1);10851086/* Prepend the current directory path */10871088strcpy (Filename, AslGbl_DirectoryPath);1089strcat (Filename, (char *) Child->Asl.Value.Buffer);10901091AslGbl_OutputFilenamePrefix = Filename;1092UtConvertBackslashes (AslGbl_OutputFilenamePrefix);10931094/*1095* Use the definition block file parameter instead of the input1096* filename. Since all files were opened previously, remove the1097* existing file and open a new file with the name of this1098* definition block parameter. Since AML code generation has yet1099* to happen, the previous file can be removed without any impacts.1100*/1101FlCloseFile (ASL_FILE_AML_OUTPUT);1102FlDeleteFile (ASL_FILE_AML_OUTPUT);1103Status = FlOpenAmlOutputFile (AslGbl_OutputFilenamePrefix);1104if (ACPI_FAILURE (Status))1105{1106AslError (ASL_ERROR, ASL_MSG_OUTPUT_FILE_OPEN, NULL, NULL);1107return;1108}1109}11101111Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;11121113/* Signature */11141115Child = Child->Asl.Next;1116Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;1117if (Child->Asl.Value.String)1118{1119AslGbl_FilesList->TableSignature = Child->Asl.Value.String;1120AslGbl_TableSignature = Child->Asl.Value.String;1121if (strlen (AslGbl_TableSignature) != ACPI_NAMESEG_SIZE)1122{1123AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,1124"Length must be exactly 4 characters");1125}11261127for (i = 0; i < ACPI_NAMESEG_SIZE; i++)1128{1129if (!isalnum ((int) AslGbl_TableSignature[i]))1130{1131AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,1132"Contains non-alphanumeric characters");1133}1134}1135}11361137/* Revision */11381139Child = Child->Asl.Next;1140Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;11411142/*1143* We used the revision to set the integer width earlier1144*/11451146/* OEMID */11471148Child = Child->Asl.Next;1149Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;1150if (Child->Asl.Value.String &&1151strlen (Child->Asl.Value.String) > ACPI_OEM_ID_SIZE)1152{1153AslError (ASL_ERROR, ASL_MSG_OEM_ID, Child,1154"Length cannot exceed 6 characters");1155}11561157/* OEM TableID */11581159Child = Child->Asl.Next;1160Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;1161if (Child->Asl.Value.String)1162{1163Length = strlen (Child->Asl.Value.String);1164if (Length > ACPI_OEM_TABLE_ID_SIZE)1165{1166AslError (ASL_ERROR, ASL_MSG_OEM_TABLE_ID, Child,1167"Length cannot exceed 8 characters");1168}11691170AslGbl_TableId = UtLocalCacheCalloc (Length + 1);1171strcpy (AslGbl_TableId, Child->Asl.Value.String);1172AslGbl_FilesList->TableId = AslGbl_TableId;11731174/*1175* Convert anything non-alphanumeric to an underscore. This1176* allows us to use the TableID to generate unique C symbols.1177*/1178for (i = 0; i < Length; i++)1179{1180if (!isalnum ((int) AslGbl_TableId[i]))1181{1182AslGbl_TableId[i] = '_';1183}1184}1185}11861187/* OEM Revision */11881189Child = Child->Asl.Next;1190Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;1191}119211931194/*******************************************************************************1195*1196* FUNCTION: UtGetArg1197*1198* PARAMETERS: Op - Get an argument for this op1199* Argn - Nth argument to get1200*1201* RETURN: The argument (as an Op object). NULL if argument does not exist1202*1203* DESCRIPTION: Get the specified op's argument (peer)1204*1205******************************************************************************/12061207ACPI_PARSE_OBJECT *1208UtGetArg (1209ACPI_PARSE_OBJECT *Op,1210UINT32 Argn)1211{1212ACPI_PARSE_OBJECT *Arg = NULL;121312141215/* Get the requested argument object */12161217Arg = Op->Asl.Child;1218while (Arg && Argn)1219{1220Argn--;1221Arg = Arg->Asl.Next;1222}12231224return (Arg);1225}122612271228/*******************************************************************************1229*1230* FUNCTION: OpnAttachNameToNode1231*1232* PARAMETERS: Op - The parent parse node1233*1234* RETURN: None1235*1236* DESCRIPTION: For the named ASL/AML operators, get the actual name from the1237* argument list and attach it to the parent node so that we1238* can get to it quickly later.1239*1240******************************************************************************/12411242static void1243OpnAttachNameToNode (1244ACPI_PARSE_OBJECT *Op)1245{1246ACPI_PARSE_OBJECT *Child = NULL;124712481249switch (Op->Asl.AmlOpcode)1250{1251case AML_DATA_REGION_OP:1252case AML_DEVICE_OP:1253case AML_EVENT_OP:1254case AML_EXTERNAL_OP:1255case AML_METHOD_OP:1256case AML_MUTEX_OP:1257case AML_REGION_OP:1258case AML_POWER_RESOURCE_OP:1259case AML_PROCESSOR_OP:1260case AML_THERMAL_ZONE_OP:1261case AML_NAME_OP:1262case AML_SCOPE_OP:12631264Child = UtGetArg (Op, 0);1265break;12661267case AML_ALIAS_OP:12681269Child = UtGetArg (Op, 1);1270break;12711272case AML_CREATE_BIT_FIELD_OP:1273case AML_CREATE_BYTE_FIELD_OP:1274case AML_CREATE_WORD_FIELD_OP:1275case AML_CREATE_DWORD_FIELD_OP:1276case AML_CREATE_QWORD_FIELD_OP:12771278Child = UtGetArg (Op, 2);1279break;12801281case AML_CREATE_FIELD_OP:12821283Child = UtGetArg (Op, 3);1284break;12851286case AML_BANK_FIELD_OP:1287case AML_INDEX_FIELD_OP:1288case AML_FIELD_OP:12891290return;12911292default:12931294return;1295}12961297if (Child)1298{1299UtAttachNamepathToOwner (Op, Child);1300}1301}130213031304/*******************************************************************************1305*1306* FUNCTION: OpnGenerateAmlOperands1307*1308* PARAMETERS: Op - The parent parse node1309*1310* RETURN: None1311*1312* DESCRIPTION: Prepare nodes to be output as AML data and operands. The more1313* complex AML opcodes require processing of the child nodes1314* (arguments/operands).1315*1316******************************************************************************/13171318void1319OpnGenerateAmlOperands (1320ACPI_PARSE_OBJECT *Op)1321{132213231324if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)1325{1326return;1327}13281329switch (Op->Asl.ParseOpcode)1330{1331case PARSEOP_DEFINITION_BLOCK:13321333OpnDoDefinitionBlock (Op);1334break;13351336case PARSEOP_METHOD:13371338OpnDoMethod (Op);1339break;13401341case PARSEOP_MUTEX:13421343OpnDoMutex (Op);1344break;13451346case PARSEOP_FIELD:13471348OpnDoField (Op);1349break;13501351case PARSEOP_INDEXFIELD:13521353OpnDoIndexField (Op);1354break;13551356case PARSEOP_BANKFIELD:13571358OpnDoBankField (Op);1359break;13601361case PARSEOP_BUFFER:13621363OpnDoBuffer (Op);1364break;13651366case PARSEOP_LOADTABLE:13671368OpnDoLoadTable (Op);1369break;13701371case PARSEOP_OPERATIONREGION:13721373OpnDoRegion (Op);1374break;13751376case PARSEOP_RESOURCETEMPLATE:13771378RsDoResourceTemplate (Op);1379break;13801381case PARSEOP_NAMESEG:1382case PARSEOP_NAMESTRING:1383case PARSEOP_METHODCALL:1384case PARSEOP_STRING_LITERAL:1385default:13861387break;1388}13891390/* TBD: move */13911392OpnAttachNameToNode (Op);1393}139413951396