1244971Sjkim/****************************************************************************** 2244971Sjkim * 3244971Sjkim * Module Name: aslxref - Namespace cross-reference 4244971Sjkim * 5244971Sjkim *****************************************************************************/ 6244971Sjkim 7244971Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 9244971Sjkim * All rights reserved. 10244971Sjkim * 11244971Sjkim * Redistribution and use in source and binary forms, with or without 12244971Sjkim * modification, are permitted provided that the following conditions 13244971Sjkim * are met: 14244971Sjkim * 1. Redistributions of source code must retain the above copyright 15244971Sjkim * notice, this list of conditions, and the following disclaimer, 16244971Sjkim * without modification. 17244971Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18244971Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19244971Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20244971Sjkim * including a substantially similar Disclaimer requirement for further 21244971Sjkim * binary redistribution. 22244971Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23244971Sjkim * of any contributors may be used to endorse or promote products derived 24244971Sjkim * from this software without specific prior written permission. 25244971Sjkim * 26244971Sjkim * Alternatively, this software may be distributed under the terms of the 27244971Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28244971Sjkim * Software Foundation. 29244971Sjkim * 30244971Sjkim * NO WARRANTY 31244971Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32244971Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33244971Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34244971Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35244971Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36244971Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37244971Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38244971Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39244971Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40244971Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41244971Sjkim * POSSIBILITY OF SUCH DAMAGES. 42244971Sjkim */ 43244971Sjkim 44244971Sjkim 45245582Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 46244971Sjkim#include "aslcompiler.y.h" 47245582Sjkim#include <contrib/dev/acpica/include/acparser.h> 48245582Sjkim#include <contrib/dev/acpica/include/amlcode.h> 49245582Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 50245582Sjkim#include <contrib/dev/acpica/include/acdispat.h> 51244971Sjkim 52244971Sjkim 53244971Sjkim#define _COMPONENT ACPI_COMPILER 54244971Sjkim ACPI_MODULE_NAME ("aslxref") 55244971Sjkim 56244971Sjkim/* Local prototypes */ 57244971Sjkim 58244971Sjkimstatic ACPI_STATUS 59244971SjkimXfNamespaceLocateBegin ( 60244971Sjkim ACPI_PARSE_OBJECT *Op, 61244971Sjkim UINT32 Level, 62244971Sjkim void *Context); 63244971Sjkim 64244971Sjkimstatic ACPI_STATUS 65244971SjkimXfNamespaceLocateEnd ( 66244971Sjkim ACPI_PARSE_OBJECT *Op, 67244971Sjkim UINT32 Level, 68244971Sjkim void *Context); 69244971Sjkim 70244971Sjkimstatic BOOLEAN 71244971SjkimXfObjectExists ( 72244971Sjkim char *Name); 73244971Sjkim 74244971Sjkimstatic ACPI_STATUS 75244971SjkimXfCompareOneNamespaceObject ( 76244971Sjkim ACPI_HANDLE ObjHandle, 77244971Sjkim UINT32 Level, 78244971Sjkim void *Context, 79244971Sjkim void **ReturnValue); 80244971Sjkim 81244971Sjkimstatic void 82244971SjkimXfCheckFieldRange ( 83244971Sjkim ACPI_PARSE_OBJECT *Op, 84244971Sjkim UINT32 RegionBitLength, 85244971Sjkim UINT32 FieldBitOffset, 86244971Sjkim UINT32 FieldBitLength, 87244971Sjkim UINT32 AccessBitWidth); 88244971Sjkim 89244971Sjkim 90244971Sjkim/******************************************************************************* 91244971Sjkim * 92244971Sjkim * FUNCTION: XfCrossReferenceNamespace 93244971Sjkim * 94244971Sjkim * PARAMETERS: None 95244971Sjkim * 96244971Sjkim * RETURN: Status 97244971Sjkim * 98244971Sjkim * DESCRIPTION: Perform a cross reference check of the parse tree against the 99244971Sjkim * namespace. Every named referenced within the parse tree 100244971Sjkim * should be get resolved with a namespace lookup. If not, the 101244971Sjkim * original reference in the ASL code is invalid -- i.e., refers 102244971Sjkim * to a non-existent object. 103244971Sjkim * 104244971Sjkim * NOTE: The ASL "External" operator causes the name to be inserted into the 105244971Sjkim * namespace so that references to the external name will be resolved 106244971Sjkim * correctly here. 107244971Sjkim * 108244971Sjkim ******************************************************************************/ 109244971Sjkim 110244971SjkimACPI_STATUS 111244971SjkimXfCrossReferenceNamespace ( 112244971Sjkim void) 113244971Sjkim{ 114244971Sjkim ACPI_WALK_STATE *WalkState; 115244971Sjkim 116244971Sjkim 117244971Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n"); 118244971Sjkim 119244971Sjkim /* 120244971Sjkim * Create a new walk state for use when looking up names 121244971Sjkim * within the namespace (Passed as context to the callbacks) 122244971Sjkim */ 123244971Sjkim WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 124244971Sjkim if (!WalkState) 125244971Sjkim { 126244971Sjkim return (AE_NO_MEMORY); 127244971Sjkim } 128244971Sjkim 129244971Sjkim /* Walk the entire parse tree */ 130244971Sjkim 131244971Sjkim TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, XfNamespaceLocateBegin, 132244971Sjkim XfNamespaceLocateEnd, WalkState); 133244971Sjkim return (AE_OK); 134244971Sjkim} 135244971Sjkim 136244971Sjkim 137244971Sjkim/******************************************************************************* 138244971Sjkim * 139244971Sjkim * FUNCTION: XfObjectExists 140244971Sjkim * 141244971Sjkim * PARAMETERS: Name - 4 char ACPI name 142244971Sjkim * 143244971Sjkim * RETURN: TRUE if name exists in namespace 144244971Sjkim * 145244971Sjkim * DESCRIPTION: Walk the namespace to find an object 146244971Sjkim * 147244971Sjkim ******************************************************************************/ 148244971Sjkim 149244971Sjkimstatic BOOLEAN 150244971SjkimXfObjectExists ( 151244971Sjkim char *Name) 152244971Sjkim{ 153244971Sjkim ACPI_STATUS Status; 154244971Sjkim 155244971Sjkim 156244971Sjkim /* Walk entire namespace from the supplied root */ 157244971Sjkim 158244971Sjkim Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 159244971Sjkim ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL, 160244971Sjkim Name, NULL); 161244971Sjkim if (Status == AE_CTRL_TRUE) 162244971Sjkim { 163244971Sjkim /* At least one instance of the name was found */ 164244971Sjkim 165244971Sjkim return (TRUE); 166244971Sjkim } 167244971Sjkim 168244971Sjkim return (FALSE); 169244971Sjkim} 170244971Sjkim 171244971Sjkim 172244971Sjkim/******************************************************************************* 173244971Sjkim * 174244971Sjkim * FUNCTION: XfCompareOneNamespaceObject 175244971Sjkim * 176244971Sjkim * PARAMETERS: ACPI_WALK_CALLBACK 177244971Sjkim * 178244971Sjkim * RETURN: Status 179244971Sjkim * 180244971Sjkim * DESCRIPTION: Compare name of one object. 181244971Sjkim * 182244971Sjkim ******************************************************************************/ 183244971Sjkim 184244971Sjkimstatic ACPI_STATUS 185244971SjkimXfCompareOneNamespaceObject ( 186244971Sjkim ACPI_HANDLE ObjHandle, 187244971Sjkim UINT32 Level, 188244971Sjkim void *Context, 189244971Sjkim void **ReturnValue) 190244971Sjkim{ 191244971Sjkim ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 192244971Sjkim 193244971Sjkim 194244971Sjkim /* Simply check the name */ 195244971Sjkim 196244971Sjkim if (*((UINT32 *) (Context)) == Node->Name.Integer) 197244971Sjkim { 198244971Sjkim /* Abort walk if we found one instance */ 199244971Sjkim 200244971Sjkim return (AE_CTRL_TRUE); 201244971Sjkim } 202244971Sjkim 203244971Sjkim return (AE_OK); 204244971Sjkim} 205244971Sjkim 206244971Sjkim 207244971Sjkim/******************************************************************************* 208244971Sjkim * 209244971Sjkim * FUNCTION: XfCheckFieldRange 210244971Sjkim * 211244971Sjkim * PARAMETERS: RegionBitLength - Length of entire parent region 212244971Sjkim * FieldBitOffset - Start of the field unit (within region) 213244971Sjkim * FieldBitLength - Entire length of field unit 214244971Sjkim * AccessBitWidth - Access width of the field unit 215244971Sjkim * 216244971Sjkim * RETURN: None 217244971Sjkim * 218244971Sjkim * DESCRIPTION: Check one field unit to make sure it fits in the parent 219244971Sjkim * op region. 220244971Sjkim * 221244971Sjkim * Note: AccessBitWidth must be either 8,16,32, or 64 222244971Sjkim * 223244971Sjkim ******************************************************************************/ 224244971Sjkim 225244971Sjkimstatic void 226244971SjkimXfCheckFieldRange ( 227244971Sjkim ACPI_PARSE_OBJECT *Op, 228244971Sjkim UINT32 RegionBitLength, 229244971Sjkim UINT32 FieldBitOffset, 230244971Sjkim UINT32 FieldBitLength, 231244971Sjkim UINT32 AccessBitWidth) 232244971Sjkim{ 233244971Sjkim UINT32 FieldEndBitOffset; 234244971Sjkim 235244971Sjkim 236244971Sjkim /* 237244971Sjkim * Check each field unit against the region size. The entire 238244971Sjkim * field unit (start offset plus length) must fit within the 239244971Sjkim * region. 240244971Sjkim */ 241244971Sjkim FieldEndBitOffset = FieldBitOffset + FieldBitLength; 242244971Sjkim 243244971Sjkim if (FieldEndBitOffset > RegionBitLength) 244244971Sjkim { 245244971Sjkim /* Field definition itself is beyond the end-of-region */ 246244971Sjkim 247244971Sjkim AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL); 248244971Sjkim return; 249244971Sjkim } 250244971Sjkim 251244971Sjkim /* 252244971Sjkim * Now check that the field plus AccessWidth doesn't go beyond 253244971Sjkim * the end-of-region. Assumes AccessBitWidth is a power of 2 254244971Sjkim */ 255244971Sjkim FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth); 256244971Sjkim 257244971Sjkim if (FieldEndBitOffset > RegionBitLength) 258244971Sjkim { 259244971Sjkim /* Field definition combined with the access is beyond EOR */ 260244971Sjkim 261244971Sjkim AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL); 262244971Sjkim } 263244971Sjkim} 264244971Sjkim 265244971Sjkim/******************************************************************************* 266244971Sjkim * 267244971Sjkim * FUNCTION: XfNamespaceLocateBegin 268244971Sjkim * 269244971Sjkim * PARAMETERS: ASL_WALK_CALLBACK 270244971Sjkim * 271244971Sjkim * RETURN: Status 272244971Sjkim * 273244971Sjkim * DESCRIPTION: Descending callback used during cross-reference. For named 274244971Sjkim * object references, attempt to locate the name in the 275244971Sjkim * namespace. 276244971Sjkim * 277244971Sjkim * NOTE: ASL references to named fields within resource descriptors are 278244971Sjkim * resolved to integer values here. Therefore, this step is an 279244971Sjkim * important part of the code generation. We don't know that the 280244971Sjkim * name refers to a resource descriptor until now. 281244971Sjkim * 282244971Sjkim ******************************************************************************/ 283244971Sjkim 284244971Sjkimstatic ACPI_STATUS 285244971SjkimXfNamespaceLocateBegin ( 286244971Sjkim ACPI_PARSE_OBJECT *Op, 287244971Sjkim UINT32 Level, 288244971Sjkim void *Context) 289244971Sjkim{ 290244971Sjkim ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 291244971Sjkim ACPI_NAMESPACE_NODE *Node; 292244971Sjkim ACPI_STATUS Status; 293244971Sjkim ACPI_OBJECT_TYPE ObjectType; 294244971Sjkim char *Path; 295244971Sjkim UINT8 PassedArgs; 296244971Sjkim ACPI_PARSE_OBJECT *NextOp; 297244971Sjkim ACPI_PARSE_OBJECT *OwningOp; 298244971Sjkim ACPI_PARSE_OBJECT *SpaceIdOp; 299244971Sjkim UINT32 MinimumLength; 300244971Sjkim UINT32 Offset; 301244971Sjkim UINT32 FieldBitLength; 302244971Sjkim UINT32 TagBitLength; 303244971Sjkim UINT8 Message = 0; 304244971Sjkim const ACPI_OPCODE_INFO *OpInfo; 305244971Sjkim UINT32 Flags; 306244971Sjkim 307244971Sjkim 308244971Sjkim ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op); 309244971Sjkim 310244971Sjkim /* 311244971Sjkim * If this node is the actual declaration of a name 312244971Sjkim * [such as the XXXX name in "Method (XXXX)"], 313244971Sjkim * we are not interested in it here. We only care about names that are 314244971Sjkim * references to other objects within the namespace and the parent objects 315244971Sjkim * of name declarations 316244971Sjkim */ 317244971Sjkim if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) 318244971Sjkim { 319244971Sjkim return (AE_OK); 320244971Sjkim } 321244971Sjkim 322244971Sjkim /* We are only interested in opcodes that have an associated name */ 323244971Sjkim 324244971Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 325244971Sjkim 326244971Sjkim if ((!(OpInfo->Flags & AML_NAMED)) && 327244971Sjkim (!(OpInfo->Flags & AML_CREATE)) && 328244971Sjkim (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && 329244971Sjkim (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) && 330244971Sjkim (Op->Asl.ParseOpcode != PARSEOP_METHODCALL)) 331244971Sjkim { 332244971Sjkim return (AE_OK); 333244971Sjkim } 334244971Sjkim 335244971Sjkim /* 336244971Sjkim * One special case: CondRefOf operator - we don't care if the name exists 337244971Sjkim * or not at this point, just ignore it, the point of the operator is to 338244971Sjkim * determine if the name exists at runtime. 339244971Sjkim */ 340244971Sjkim if ((Op->Asl.Parent) && 341244971Sjkim (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)) 342244971Sjkim { 343244971Sjkim return (AE_OK); 344244971Sjkim } 345244971Sjkim 346244971Sjkim /* 347244971Sjkim * We must enable the "search-to-root" for single NameSegs, but 348244971Sjkim * we have to be very careful about opening up scopes 349244971Sjkim */ 350244971Sjkim Flags = ACPI_NS_SEARCH_PARENT; 351244971Sjkim if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 352244971Sjkim (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 353244971Sjkim (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 354244971Sjkim { 355244971Sjkim /* 356244971Sjkim * These are name references, do not push the scope stack 357244971Sjkim * for them. 358244971Sjkim */ 359244971Sjkim Flags |= ACPI_NS_DONT_OPEN_SCOPE; 360244971Sjkim } 361244971Sjkim 362244971Sjkim /* Get the NamePath from the appropriate place */ 363244971Sjkim 364244971Sjkim if (OpInfo->Flags & AML_NAMED) 365244971Sjkim { 366244971Sjkim /* For nearly all NAMED operators, the name reference is the first child */ 367244971Sjkim 368244971Sjkim Path = Op->Asl.Child->Asl.Value.String; 369244971Sjkim if (Op->Asl.AmlOpcode == AML_ALIAS_OP) 370244971Sjkim { 371244971Sjkim /* 372244971Sjkim * ALIAS is the only oddball opcode, the name declaration 373244971Sjkim * (alias name) is the second operand 374244971Sjkim */ 375244971Sjkim Path = Op->Asl.Child->Asl.Next->Asl.Value.String; 376244971Sjkim } 377244971Sjkim } 378244971Sjkim else if (OpInfo->Flags & AML_CREATE) 379244971Sjkim { 380244971Sjkim /* Name must appear as the last parameter */ 381244971Sjkim 382244971Sjkim NextOp = Op->Asl.Child; 383244971Sjkim while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) 384244971Sjkim { 385244971Sjkim NextOp = NextOp->Asl.Next; 386244971Sjkim } 387244971Sjkim Path = NextOp->Asl.Value.String; 388244971Sjkim } 389244971Sjkim else 390244971Sjkim { 391244971Sjkim Path = Op->Asl.Value.String; 392244971Sjkim } 393244971Sjkim 394244971Sjkim ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 395244971Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 396244971Sjkim "Type=%s\n", AcpiUtGetTypeName (ObjectType))); 397244971Sjkim 398244971Sjkim /* 399244971Sjkim * Lookup the name in the namespace. Name must exist at this point, or it 400244971Sjkim * is an invalid reference. 401244971Sjkim * 402244971Sjkim * The namespace is also used as a lookup table for references to resource 403244971Sjkim * descriptors and the fields within them. 404244971Sjkim */ 405244971Sjkim Gbl_NsLookupCount++; 406244971Sjkim 407244971Sjkim Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 408244971Sjkim ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node)); 409244971Sjkim if (ACPI_FAILURE (Status)) 410244971Sjkim { 411244971Sjkim if (Status == AE_NOT_FOUND) 412244971Sjkim { 413244971Sjkim /* 414244971Sjkim * We didn't find the name reference by path -- we can qualify this 415244971Sjkim * a little better before we print an error message 416244971Sjkim */ 417244971Sjkim if (strlen (Path) == ACPI_NAME_SIZE) 418244971Sjkim { 419244971Sjkim /* A simple, one-segment ACPI name */ 420244971Sjkim 421244971Sjkim if (XfObjectExists (Path)) 422244971Sjkim { 423244971Sjkim /* 424244971Sjkim * There exists such a name, but we couldn't get to it 425244971Sjkim * from this scope 426244971Sjkim */ 427244971Sjkim AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, 428244971Sjkim Op->Asl.ExternalName); 429244971Sjkim } 430244971Sjkim else 431244971Sjkim { 432244971Sjkim /* The name doesn't exist, period */ 433244971Sjkim 434244971Sjkim AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, 435244971Sjkim Op, Op->Asl.ExternalName); 436244971Sjkim } 437244971Sjkim } 438244971Sjkim else 439244971Sjkim { 440244971Sjkim /* Check for a fully qualified path */ 441244971Sjkim 442244971Sjkim if (Path[0] == AML_ROOT_PREFIX) 443244971Sjkim { 444244971Sjkim /* Gave full path, the object does not exist */ 445244971Sjkim 446244971Sjkim AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, 447244971Sjkim Op->Asl.ExternalName); 448244971Sjkim } 449244971Sjkim else 450244971Sjkim { 451244971Sjkim /* 452244971Sjkim * We can't tell whether it doesn't exist or just 453244971Sjkim * can't be reached. 454244971Sjkim */ 455244971Sjkim AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, 456244971Sjkim Op->Asl.ExternalName); 457244971Sjkim } 458244971Sjkim } 459244971Sjkim 460244971Sjkim Status = AE_OK; 461244971Sjkim } 462244971Sjkim return (Status); 463244971Sjkim } 464244971Sjkim 465244971Sjkim /* Check for a reference vs. name declaration */ 466244971Sjkim 467244971Sjkim if (!(OpInfo->Flags & AML_NAMED) && 468244971Sjkim !(OpInfo->Flags & AML_CREATE)) 469244971Sjkim { 470244971Sjkim /* This node has been referenced, mark it for reference check */ 471244971Sjkim 472244971Sjkim Node->Flags |= ANOBJ_IS_REFERENCED; 473244971Sjkim } 474244971Sjkim 475244971Sjkim /* Attempt to optimize the NamePath */ 476244971Sjkim 477244971Sjkim OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node); 478244971Sjkim 479244971Sjkim /* 480244971Sjkim * 1) Dereference an alias (A name reference that is an alias) 481244971Sjkim * Aliases are not nested, the alias always points to the final object 482244971Sjkim */ 483244971Sjkim if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && 484244971Sjkim (Node->Type == ACPI_TYPE_LOCAL_ALIAS)) 485244971Sjkim { 486244971Sjkim /* This node points back to the original PARSEOP_ALIAS */ 487244971Sjkim 488244971Sjkim NextOp = Node->Op; 489244971Sjkim 490244971Sjkim /* The first child is the alias target op */ 491244971Sjkim 492244971Sjkim NextOp = NextOp->Asl.Child; 493244971Sjkim 494244971Sjkim /* That in turn points back to original target alias node */ 495244971Sjkim 496244971Sjkim if (NextOp->Asl.Node) 497244971Sjkim { 498244971Sjkim Node = NextOp->Asl.Node; 499244971Sjkim } 500244971Sjkim 501244971Sjkim /* Else - forward reference to alias, will be resolved later */ 502244971Sjkim } 503244971Sjkim 504244971Sjkim /* 2) Check for a reference to a resource descriptor */ 505244971Sjkim 506244971Sjkim if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 507244971Sjkim (Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 508244971Sjkim { 509244971Sjkim /* 510244971Sjkim * This was a reference to a field within a resource descriptor. 511244971Sjkim * Extract the associated field offset (either a bit or byte 512244971Sjkim * offset depending on the field type) and change the named 513244971Sjkim * reference into an integer for AML code generation 514244971Sjkim */ 515244971Sjkim Offset = Node->Value; 516244971Sjkim TagBitLength = Node->Length; 517244971Sjkim 518244971Sjkim /* 519244971Sjkim * If a field is being created, generate the length (in bits) of 520244971Sjkim * the field. Note: Opcodes other than CreateXxxField and Index 521244971Sjkim * can come through here. For other opcodes, we just need to 522244971Sjkim * convert the resource tag reference to an integer offset. 523244971Sjkim */ 524244971Sjkim switch (Op->Asl.Parent->Asl.AmlOpcode) 525244971Sjkim { 526244971Sjkim case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */ 527244971Sjkim /* 528244971Sjkim * We know the length operand is an integer constant because 529244971Sjkim * we know that it contains a reference to a resource 530244971Sjkim * descriptor tag. 531244971Sjkim */ 532244971Sjkim FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer; 533244971Sjkim break; 534244971Sjkim 535244971Sjkim case AML_CREATE_BIT_FIELD_OP: 536250838Sjkim 537244971Sjkim FieldBitLength = 1; 538244971Sjkim break; 539244971Sjkim 540244971Sjkim case AML_CREATE_BYTE_FIELD_OP: 541244971Sjkim case AML_INDEX_OP: 542250838Sjkim 543244971Sjkim FieldBitLength = 8; 544244971Sjkim break; 545244971Sjkim 546244971Sjkim case AML_CREATE_WORD_FIELD_OP: 547250838Sjkim 548244971Sjkim FieldBitLength = 16; 549244971Sjkim break; 550244971Sjkim 551244971Sjkim case AML_CREATE_DWORD_FIELD_OP: 552250838Sjkim 553244971Sjkim FieldBitLength = 32; 554244971Sjkim break; 555244971Sjkim 556244971Sjkim case AML_CREATE_QWORD_FIELD_OP: 557250838Sjkim 558244971Sjkim FieldBitLength = 64; 559244971Sjkim break; 560244971Sjkim 561244971Sjkim default: 562250838Sjkim 563244971Sjkim FieldBitLength = 0; 564244971Sjkim break; 565244971Sjkim } 566244971Sjkim 567244971Sjkim /* Check the field length against the length of the resource tag */ 568244971Sjkim 569244971Sjkim if (FieldBitLength) 570244971Sjkim { 571244971Sjkim if (TagBitLength < FieldBitLength) 572244971Sjkim { 573244971Sjkim Message = ASL_MSG_TAG_SMALLER; 574244971Sjkim } 575244971Sjkim else if (TagBitLength > FieldBitLength) 576244971Sjkim { 577244971Sjkim Message = ASL_MSG_TAG_LARGER; 578244971Sjkim } 579244971Sjkim 580244971Sjkim if (Message) 581244971Sjkim { 582244971Sjkim sprintf (MsgBuffer, "Size mismatch, Tag: %u bit%s, Field: %u bit%s", 583244971Sjkim TagBitLength, (TagBitLength > 1) ? "s" : "", 584244971Sjkim FieldBitLength, (FieldBitLength > 1) ? "s" : ""); 585244971Sjkim 586244971Sjkim AslError (ASL_WARNING, Message, Op, MsgBuffer); 587244971Sjkim } 588244971Sjkim } 589244971Sjkim 590244971Sjkim /* Convert the BitOffset to a ByteOffset for certain opcodes */ 591244971Sjkim 592244971Sjkim switch (Op->Asl.Parent->Asl.AmlOpcode) 593244971Sjkim { 594244971Sjkim case AML_CREATE_BYTE_FIELD_OP: 595244971Sjkim case AML_CREATE_WORD_FIELD_OP: 596244971Sjkim case AML_CREATE_DWORD_FIELD_OP: 597244971Sjkim case AML_CREATE_QWORD_FIELD_OP: 598244971Sjkim case AML_INDEX_OP: 599244971Sjkim 600244971Sjkim Offset = ACPI_DIV_8 (Offset); 601244971Sjkim break; 602244971Sjkim 603244971Sjkim default: 604250838Sjkim 605244971Sjkim break; 606244971Sjkim } 607244971Sjkim 608244971Sjkim /* Now convert this node to an integer whose value is the field offset */ 609244971Sjkim 610244971Sjkim Op->Asl.AmlLength = 0; 611244971Sjkim Op->Asl.ParseOpcode = PARSEOP_INTEGER; 612244971Sjkim Op->Asl.Value.Integer = (UINT64) Offset; 613244971Sjkim Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD; 614244971Sjkim 615244971Sjkim OpcGenerateAmlOpcode (Op); 616244971Sjkim } 617244971Sjkim 618244971Sjkim /* 3) Check for a method invocation */ 619244971Sjkim 620244971Sjkim else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) && 621244971Sjkim (Node->Type == ACPI_TYPE_METHOD) && 622244971Sjkim (Op->Asl.Parent) && 623244971Sjkim (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) || 624244971Sjkim 625244971Sjkim (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 626244971Sjkim { 627244971Sjkim 628244971Sjkim /* 629244971Sjkim * A reference to a method within one of these opcodes is not an 630244971Sjkim * invocation of the method, it is simply a reference to the method. 631244971Sjkim */ 632244971Sjkim if ((Op->Asl.Parent) && 633244971Sjkim ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) || 634244971Sjkim (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) || 635244971Sjkim (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE))) 636244971Sjkim { 637244971Sjkim return (AE_OK); 638244971Sjkim } 639244971Sjkim /* 640244971Sjkim * There are two types of method invocation: 641244971Sjkim * 1) Invocation with arguments -- the parser recognizes this 642244971Sjkim * as a METHODCALL. 643244971Sjkim * 2) Invocation with no arguments --the parser cannot determine that 644244971Sjkim * this is a method invocation, therefore we have to figure it out 645244971Sjkim * here. 646244971Sjkim */ 647244971Sjkim if (Node->Type != ACPI_TYPE_METHOD) 648244971Sjkim { 649244971Sjkim sprintf (MsgBuffer, "%s is a %s", 650244971Sjkim Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); 651244971Sjkim 652244971Sjkim AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer); 653244971Sjkim return (AE_OK); 654244971Sjkim } 655244971Sjkim 656244971Sjkim /* Save the method node in the caller's op */ 657244971Sjkim 658244971Sjkim Op->Asl.Node = Node; 659244971Sjkim if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF) 660244971Sjkim { 661244971Sjkim return (AE_OK); 662244971Sjkim } 663244971Sjkim 664244971Sjkim /* 665244971Sjkim * This is a method invocation, with or without arguments. 666244971Sjkim * Count the number of arguments, each appears as a child 667244971Sjkim * under the parent node 668244971Sjkim */ 669244971Sjkim Op->Asl.ParseOpcode = PARSEOP_METHODCALL; 670244971Sjkim UtSetParseOpName (Op); 671244971Sjkim 672244971Sjkim PassedArgs = 0; 673244971Sjkim NextOp = Op->Asl.Child; 674244971Sjkim 675244971Sjkim while (NextOp) 676244971Sjkim { 677244971Sjkim PassedArgs++; 678244971Sjkim NextOp = NextOp->Asl.Next; 679244971Sjkim } 680244971Sjkim 681244971Sjkim if (Node->Value != ASL_EXTERNAL_METHOD) 682244971Sjkim { 683244971Sjkim /* 684244971Sjkim * Check the parsed arguments with the number expected by the 685244971Sjkim * method declaration itself 686244971Sjkim */ 687244971Sjkim if (PassedArgs != Node->Value) 688244971Sjkim { 689244971Sjkim sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName, 690244971Sjkim Node->Value); 691244971Sjkim 692244971Sjkim if (PassedArgs < Node->Value) 693244971Sjkim { 694244971Sjkim AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer); 695244971Sjkim } 696244971Sjkim else 697244971Sjkim { 698244971Sjkim AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer); 699244971Sjkim } 700244971Sjkim } 701244971Sjkim } 702244971Sjkim } 703244971Sjkim 704244971Sjkim /* 4) Check for an ASL Field definition */ 705244971Sjkim 706244971Sjkim else if ((Op->Asl.Parent) && 707244971Sjkim ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) || 708244971Sjkim (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD))) 709244971Sjkim { 710244971Sjkim /* 711244971Sjkim * Offset checking for fields. If the parent operation region has a 712244971Sjkim * constant length (known at compile time), we can check fields 713244971Sjkim * defined in that region against the region length. This will catch 714244971Sjkim * fields and field units that cannot possibly fit within the region. 715244971Sjkim * 716244971Sjkim * Note: Index fields do not directly reference an operation region, 717244971Sjkim * thus they are not included in this check. 718244971Sjkim */ 719244971Sjkim if (Op == Op->Asl.Parent->Asl.Child) 720244971Sjkim { 721244971Sjkim /* 722244971Sjkim * This is the first child of the field node, which is 723244971Sjkim * the name of the region. Get the parse node for the 724244971Sjkim * region -- which contains the length of the region. 725244971Sjkim */ 726244971Sjkim OwningOp = Node->Op; 727244971Sjkim Op->Asl.Parent->Asl.ExtraValue = 728244971Sjkim ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer); 729244971Sjkim 730244971Sjkim /* Examine the field access width */ 731244971Sjkim 732244971Sjkim switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer) 733244971Sjkim { 734244971Sjkim case AML_FIELD_ACCESS_ANY: 735244971Sjkim case AML_FIELD_ACCESS_BYTE: 736244971Sjkim case AML_FIELD_ACCESS_BUFFER: 737244971Sjkim default: 738250838Sjkim 739244971Sjkim MinimumLength = 1; 740244971Sjkim break; 741244971Sjkim 742244971Sjkim case AML_FIELD_ACCESS_WORD: 743250838Sjkim 744244971Sjkim MinimumLength = 2; 745244971Sjkim break; 746244971Sjkim 747244971Sjkim case AML_FIELD_ACCESS_DWORD: 748250838Sjkim 749244971Sjkim MinimumLength = 4; 750244971Sjkim break; 751244971Sjkim 752244971Sjkim case AML_FIELD_ACCESS_QWORD: 753250838Sjkim 754244971Sjkim MinimumLength = 8; 755244971Sjkim break; 756244971Sjkim } 757244971Sjkim 758244971Sjkim /* 759244971Sjkim * Is the region at least as big as the access width? 760244971Sjkim * Note: DataTableRegions have 0 length 761244971Sjkim */ 762244971Sjkim if (((UINT32) OwningOp->Asl.Value.Integer) && 763244971Sjkim ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength)) 764244971Sjkim { 765244971Sjkim AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL); 766244971Sjkim } 767244971Sjkim 768244971Sjkim /* 769244971Sjkim * Check EC/CMOS/SMBUS fields to make sure that the correct 770244971Sjkim * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS) 771244971Sjkim */ 772244971Sjkim SpaceIdOp = OwningOp->Asl.Child->Asl.Next; 773244971Sjkim switch ((UINT32) SpaceIdOp->Asl.Value.Integer) 774244971Sjkim { 775244971Sjkim case ACPI_ADR_SPACE_EC: 776244971Sjkim case ACPI_ADR_SPACE_CMOS: 777244971Sjkim case ACPI_ADR_SPACE_GPIO: 778244971Sjkim 779244971Sjkim if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE) 780244971Sjkim { 781244971Sjkim AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL); 782244971Sjkim } 783244971Sjkim break; 784244971Sjkim 785244971Sjkim case ACPI_ADR_SPACE_SMBUS: 786244971Sjkim case ACPI_ADR_SPACE_IPMI: 787244971Sjkim case ACPI_ADR_SPACE_GSBUS: 788244971Sjkim 789244971Sjkim if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER) 790244971Sjkim { 791244971Sjkim AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL); 792244971Sjkim } 793244971Sjkim break; 794244971Sjkim 795244971Sjkim default: 796244971Sjkim 797244971Sjkim /* Nothing to do for other address spaces */ 798250838Sjkim 799244971Sjkim break; 800244971Sjkim } 801244971Sjkim } 802244971Sjkim else 803244971Sjkim { 804244971Sjkim /* 805244971Sjkim * This is one element of the field list. Check to make sure 806244971Sjkim * that it does not go beyond the end of the parent operation region. 807244971Sjkim * 808244971Sjkim * In the code below: 809244971Sjkim * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits) 810244971Sjkim * Op->Asl.ExtraValue - Field start offset (bits) 811244971Sjkim * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits) 812244971Sjkim * Op->Asl.Child->Asl.ExtraValue - Field access width (bits) 813244971Sjkim */ 814244971Sjkim if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child) 815244971Sjkim { 816244971Sjkim XfCheckFieldRange (Op, 817244971Sjkim Op->Asl.Parent->Asl.ExtraValue, 818244971Sjkim Op->Asl.ExtraValue, 819244971Sjkim (UINT32) Op->Asl.Child->Asl.Value.Integer, 820244971Sjkim Op->Asl.Child->Asl.ExtraValue); 821244971Sjkim } 822244971Sjkim } 823244971Sjkim } 824244971Sjkim 825244971Sjkim Op->Asl.Node = Node; 826244971Sjkim return (Status); 827244971Sjkim} 828244971Sjkim 829244971Sjkim 830244971Sjkim/******************************************************************************* 831244971Sjkim * 832244971Sjkim * FUNCTION: XfNamespaceLocateEnd 833244971Sjkim * 834244971Sjkim * PARAMETERS: ASL_WALK_CALLBACK 835244971Sjkim * 836244971Sjkim * RETURN: Status 837244971Sjkim * 838244971Sjkim * DESCRIPTION: Ascending callback used during cross reference. We only 839244971Sjkim * need to worry about scope management here. 840244971Sjkim * 841244971Sjkim ******************************************************************************/ 842244971Sjkim 843244971Sjkimstatic ACPI_STATUS 844244971SjkimXfNamespaceLocateEnd ( 845244971Sjkim ACPI_PARSE_OBJECT *Op, 846244971Sjkim UINT32 Level, 847244971Sjkim void *Context) 848244971Sjkim{ 849244971Sjkim ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; 850244971Sjkim const ACPI_OPCODE_INFO *OpInfo; 851244971Sjkim 852244971Sjkim 853244971Sjkim ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd); 854244971Sjkim 855244971Sjkim 856244971Sjkim /* We are only interested in opcodes that have an associated name */ 857244971Sjkim 858244971Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 859244971Sjkim if (!(OpInfo->Flags & AML_NAMED)) 860244971Sjkim { 861244971Sjkim return (AE_OK); 862244971Sjkim } 863244971Sjkim 864244971Sjkim /* Not interested in name references, we did not open a scope for them */ 865244971Sjkim 866244971Sjkim if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 867244971Sjkim (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 868244971Sjkim (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 869244971Sjkim { 870244971Sjkim return (AE_OK); 871244971Sjkim } 872244971Sjkim 873244971Sjkim /* Pop the scope stack if necessary */ 874244971Sjkim 875244971Sjkim if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) 876244971Sjkim { 877244971Sjkim 878244971Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 879244971Sjkim "%s: Popping scope for Op %p\n", 880244971Sjkim AcpiUtGetTypeName (OpInfo->ObjectType), Op)); 881244971Sjkim 882244971Sjkim (void) AcpiDsScopeStackPop (WalkState); 883244971Sjkim } 884244971Sjkim 885244971Sjkim return (AE_OK); 886244971Sjkim} 887