psargs.c revision 259065
1243789Sdim/****************************************************************************** 2243789Sdim * 3243789Sdim * Module Name: psargs - Parse AML opcode arguments 4243789Sdim * 5243789Sdim *****************************************************************************/ 6243789Sdim 7243789Sdim/* 8243789Sdim * Copyright (C) 2000 - 2013, Intel Corp. 9243789Sdim * All rights reserved. 10243789Sdim * 11243789Sdim * Redistribution and use in source and binary forms, with or without 12243789Sdim * modification, are permitted provided that the following conditions 13243789Sdim * are met: 14243789Sdim * 1. Redistributions of source code must retain the above copyright 15243789Sdim * notice, this list of conditions, and the following disclaimer, 16243789Sdim * without modification. 17243789Sdim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18243789Sdim * substantially similar to the "NO WARRANTY" disclaimer below 19243789Sdim * ("Disclaimer") and any redistribution must be conditioned upon 20243789Sdim * including a substantially similar Disclaimer requirement for further 21243789Sdim * binary redistribution. 22243789Sdim * 3. Neither the names of the above-listed copyright holders nor the names 23243789Sdim * of any contributors may be used to endorse or promote products derived 24243789Sdim * from this software without specific prior written permission. 25243789Sdim * 26243789Sdim * Alternatively, this software may be distributed under the terms of the 27243789Sdim * GNU General Public License ("GPL") version 2 as published by the Free 28243789Sdim * Software Foundation. 29243789Sdim * 30243789Sdim * NO WARRANTY 31243789Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32243789Sdim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33243789Sdim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34243789Sdim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35243789Sdim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36243789Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37243789Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38243789Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39243789Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40243789Sdim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41243789Sdim * POSSIBILITY OF SUCH DAMAGES. 42243789Sdim */ 43243789Sdim 44243789Sdim#define __PSARGS_C__ 45243789Sdim 46243789Sdim#include <contrib/dev/acpica/include/acpi.h> 47243789Sdim#include <contrib/dev/acpica/include/accommon.h> 48243789Sdim#include <contrib/dev/acpica/include/acparser.h> 49243789Sdim#include <contrib/dev/acpica/include/amlcode.h> 50243789Sdim#include <contrib/dev/acpica/include/acnamesp.h> 51243789Sdim#include <contrib/dev/acpica/include/acdispat.h> 52243789Sdim 53243789Sdim#define _COMPONENT ACPI_PARSER 54243789Sdim ACPI_MODULE_NAME ("psargs") 55243789Sdim 56243789Sdim/* Local prototypes */ 57243789Sdim 58243789Sdimstatic UINT32 59243789SdimAcpiPsGetNextPackageLength ( 60243789Sdim ACPI_PARSE_STATE *ParserState); 61243789Sdim 62243789Sdimstatic ACPI_PARSE_OBJECT * 63243789SdimAcpiPsGetNextField ( 64243789Sdim ACPI_PARSE_STATE *ParserState); 65243789Sdim 66243789Sdim 67243789Sdim/******************************************************************************* 68243789Sdim * 69243789Sdim * FUNCTION: AcpiPsGetNextPackageLength 70243789Sdim * 71243789Sdim * PARAMETERS: ParserState - Current parser state object 72243789Sdim * 73243789Sdim * RETURN: Decoded package length. On completion, the AML pointer points 74243789Sdim * past the length byte or bytes. 75243789Sdim * 76243789Sdim * DESCRIPTION: Decode and return a package length field. 77243789Sdim * Note: Largest package length is 28 bits, from ACPI specification 78243789Sdim * 79243789Sdim ******************************************************************************/ 80243789Sdim 81243789Sdimstatic UINT32 82243789SdimAcpiPsGetNextPackageLength ( 83243789Sdim ACPI_PARSE_STATE *ParserState) 84243789Sdim{ 85243789Sdim UINT8 *Aml = ParserState->Aml; 86243789Sdim UINT32 PackageLength = 0; 87243789Sdim UINT32 ByteCount; 88243789Sdim UINT8 ByteZeroMask = 0x3F; /* Default [0:5] */ 89243789Sdim 90243789Sdim 91243789Sdim ACPI_FUNCTION_TRACE (PsGetNextPackageLength); 92243789Sdim 93243789Sdim 94243789Sdim /* 95243789Sdim * Byte 0 bits [6:7] contain the number of additional bytes 96243789Sdim * used to encode the package length, either 0,1,2, or 3 97243789Sdim */ 98243789Sdim ByteCount = (Aml[0] >> 6); 99243789Sdim ParserState->Aml += ((ACPI_SIZE) ByteCount + 1); 100243789Sdim 101243789Sdim /* Get bytes 3, 2, 1 as needed */ 102243789Sdim 103243789Sdim while (ByteCount) 104243789Sdim { 105243789Sdim /* 106243789Sdim * Final bit positions for the package length bytes: 107243789Sdim * Byte3->[20:27] 108243789Sdim * Byte2->[12:19] 109243789Sdim * Byte1->[04:11] 110243789Sdim * Byte0->[00:03] 111243789Sdim */ 112243789Sdim PackageLength |= (Aml[ByteCount] << ((ByteCount << 3) - 4)); 113243789Sdim 114243789Sdim ByteZeroMask = 0x0F; /* Use bits [0:3] of byte 0 */ 115243789Sdim ByteCount--; 116243789Sdim } 117243789Sdim 118243789Sdim /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ 119243789Sdim 120243789Sdim PackageLength |= (Aml[0] & ByteZeroMask); 121243789Sdim return_UINT32 (PackageLength); 122243789Sdim} 123243789Sdim 124243789Sdim 125243789Sdim/******************************************************************************* 126243789Sdim * 127243789Sdim * FUNCTION: AcpiPsGetNextPackageEnd 128243789Sdim * 129243789Sdim * PARAMETERS: ParserState - Current parser state object 130243789Sdim * 131243789Sdim * RETURN: Pointer to end-of-package +1 132243789Sdim * 133243789Sdim * DESCRIPTION: Get next package length and return a pointer past the end of 134243789Sdim * the package. Consumes the package length field 135243789Sdim * 136243789Sdim ******************************************************************************/ 137243789Sdim 138243789SdimUINT8 * 139243789SdimAcpiPsGetNextPackageEnd ( 140243789Sdim ACPI_PARSE_STATE *ParserState) 141243789Sdim{ 142243789Sdim UINT8 *Start = ParserState->Aml; 143243789Sdim UINT32 PackageLength; 144243789Sdim 145243789Sdim 146243789Sdim ACPI_FUNCTION_TRACE (PsGetNextPackageEnd); 147243789Sdim 148243789Sdim 149243789Sdim /* Function below updates ParserState->Aml */ 150243789Sdim 151243789Sdim PackageLength = AcpiPsGetNextPackageLength (ParserState); 152243789Sdim 153243789Sdim return_PTR (Start + PackageLength); /* end of package */ 154243789Sdim} 155243789Sdim 156243789Sdim 157243789Sdim/******************************************************************************* 158243789Sdim * 159243789Sdim * FUNCTION: AcpiPsGetNextNamestring 160243789Sdim * 161243789Sdim * PARAMETERS: ParserState - Current parser state object 162243789Sdim * 163243789Sdim * RETURN: Pointer to the start of the name string (pointer points into 164243789Sdim * the AML. 165243789Sdim * 166243789Sdim * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name 167243789Sdim * prefix characters. Set parser state to point past the string. 168243789Sdim * (Name is consumed from the AML.) 169243789Sdim * 170243789Sdim ******************************************************************************/ 171243789Sdim 172243789Sdimchar * 173243789SdimAcpiPsGetNextNamestring ( 174243789Sdim ACPI_PARSE_STATE *ParserState) 175243789Sdim{ 176243789Sdim UINT8 *Start = ParserState->Aml; 177243789Sdim UINT8 *End = ParserState->Aml; 178243789Sdim 179243789Sdim 180243789Sdim ACPI_FUNCTION_TRACE (PsGetNextNamestring); 181243789Sdim 182243789Sdim 183243789Sdim /* Point past any namestring prefix characters (backslash or carat) */ 184243789Sdim 185243789Sdim while (ACPI_IS_ROOT_PREFIX (*End) || 186243789Sdim ACPI_IS_PARENT_PREFIX (*End)) 187243789Sdim { 188243789Sdim End++; 189243789Sdim } 190243789Sdim 191243789Sdim /* Decode the path prefix character */ 192243789Sdim 193243789Sdim switch (*End) 194243789Sdim { 195243789Sdim case 0: 196243789Sdim 197243789Sdim /* NullName */ 198243789Sdim 199243789Sdim if (End == Start) 200243789Sdim { 201243789Sdim Start = NULL; 202243789Sdim } 203243789Sdim End++; 204243789Sdim break; 205243789Sdim 206243789Sdim case AML_DUAL_NAME_PREFIX: 207243789Sdim 208243789Sdim /* Two name segments */ 209243789Sdim 210243789Sdim End += 1 + (2 * ACPI_NAME_SIZE); 211243789Sdim break; 212243789Sdim 213243789Sdim case AML_MULTI_NAME_PREFIX_OP: 214243789Sdim 215243789Sdim /* Multiple name segments, 4 chars each, count in next byte */ 216243789Sdim 217243789Sdim End += 2 + (*(End + 1) * ACPI_NAME_SIZE); 218243789Sdim break; 219243789Sdim 220243789Sdim default: 221243789Sdim 222243789Sdim /* Single name segment */ 223243789Sdim 224243789Sdim End += ACPI_NAME_SIZE; 225243789Sdim break; 226243789Sdim } 227243789Sdim 228243789Sdim ParserState->Aml = End; 229243789Sdim return_PTR ((char *) Start); 230243789Sdim} 231243789Sdim 232243789Sdim 233243789Sdim/******************************************************************************* 234243789Sdim * 235243789Sdim * FUNCTION: AcpiPsGetNextNamepath 236243789Sdim * 237243789Sdim * PARAMETERS: ParserState - Current parser state object 238243789Sdim * Arg - Where the namepath will be stored 239243789Sdim * ArgCount - If the namepath points to a control method 240243789Sdim * the method's argument is returned here. 241243789Sdim * PossibleMethodCall - Whether the namepath can possibly be the 242243789Sdim * start of a method call 243243789Sdim * 244243789Sdim * RETURN: Status 245243789Sdim * 246243789Sdim * DESCRIPTION: Get next name (if method call, return # of required args). 247243789Sdim * Names are looked up in the internal namespace to determine 248243789Sdim * if the name represents a control method. If a method 249243789Sdim * is found, the number of arguments to the method is returned. 250243789Sdim * This information is critical for parsing to continue correctly. 251243789Sdim * 252243789Sdim ******************************************************************************/ 253243789Sdim 254243789SdimACPI_STATUS 255243789SdimAcpiPsGetNextNamepath ( 256243789Sdim ACPI_WALK_STATE *WalkState, 257243789Sdim ACPI_PARSE_STATE *ParserState, 258243789Sdim ACPI_PARSE_OBJECT *Arg, 259243789Sdim BOOLEAN PossibleMethodCall) 260243789Sdim{ 261243789Sdim ACPI_STATUS Status; 262243789Sdim char *Path; 263243789Sdim ACPI_PARSE_OBJECT *NameOp; 264243789Sdim ACPI_OPERAND_OBJECT *MethodDesc; 265243789Sdim ACPI_NAMESPACE_NODE *Node; 266243789Sdim UINT8 *Start = ParserState->Aml; 267243789Sdim 268243789Sdim 269243789Sdim ACPI_FUNCTION_TRACE (PsGetNextNamepath); 270243789Sdim 271243789Sdim 272243789Sdim Path = AcpiPsGetNextNamestring (ParserState); 273243789Sdim AcpiPsInitOp (Arg, AML_INT_NAMEPATH_OP); 274243789Sdim 275243789Sdim /* Null path case is allowed, just exit */ 276243789Sdim 277243789Sdim if (!Path) 278243789Sdim { 279243789Sdim Arg->Common.Value.Name = Path; 280243789Sdim return_ACPI_STATUS (AE_OK); 281243789Sdim } 282243789Sdim 283243789Sdim /* 284243789Sdim * Lookup the name in the internal namespace, starting with the current 285243789Sdim * scope. We don't want to add anything new to the namespace here, 286243789Sdim * however, so we use MODE_EXECUTE. 287243789Sdim * Allow searching of the parent tree, but don't open a new scope - 288243789Sdim * we just want to lookup the object (must be mode EXECUTE to perform 289243789Sdim * the upsearch) 290243789Sdim */ 291243789Sdim Status = AcpiNsLookup (WalkState->ScopeInfo, Path, 292243789Sdim ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 293243789Sdim ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); 294243789Sdim 295243789Sdim /* 296243789Sdim * If this name is a control method invocation, we must 297243789Sdim * setup the method call 298243789Sdim */ 299243789Sdim if (ACPI_SUCCESS (Status) && 300243789Sdim PossibleMethodCall && 301243789Sdim (Node->Type == ACPI_TYPE_METHOD)) 302243789Sdim { 303243789Sdim if (WalkState->Opcode == AML_UNLOAD_OP) 304243789Sdim { 305243789Sdim /* 306243789Sdim * AcpiPsGetNextNamestring has increased the AML pointer, 307243789Sdim * so we need to restore the saved AML pointer for method call. 308243789Sdim */ 309243789Sdim WalkState->ParserState.Aml = Start; 310243789Sdim WalkState->ArgCount = 1; 311243789Sdim AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP); 312243789Sdim return_ACPI_STATUS (AE_OK); 313243789Sdim } 314243789Sdim 315243789Sdim /* This name is actually a control method invocation */ 316243789Sdim 317243789Sdim MethodDesc = AcpiNsGetAttachedObject (Node); 318243789Sdim ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 319243789Sdim "Control Method - %p Desc %p Path=%p\n", Node, MethodDesc, Path)); 320243789Sdim 321243789Sdim NameOp = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); 322243789Sdim if (!NameOp) 323243789Sdim { 324243789Sdim return_ACPI_STATUS (AE_NO_MEMORY); 325243789Sdim } 326243789Sdim 327243789Sdim /* Change Arg into a METHOD CALL and attach name to it */ 328243789Sdim 329243789Sdim AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP); 330243789Sdim NameOp->Common.Value.Name = Path; 331243789Sdim 332243789Sdim /* Point METHODCALL/NAME to the METHOD Node */ 333243789Sdim 334243789Sdim NameOp->Common.Node = Node; 335243789Sdim AcpiPsAppendArg (Arg, NameOp); 336243789Sdim 337243789Sdim if (!MethodDesc) 338243789Sdim { 339243789Sdim ACPI_ERROR ((AE_INFO, 340243789Sdim "Control Method %p has no attached object", 341243789Sdim Node)); 342243789Sdim return_ACPI_STATUS (AE_AML_INTERNAL); 343243789Sdim } 344243789Sdim 345243789Sdim ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 346243789Sdim "Control Method - %p Args %X\n", 347243789Sdim Node, MethodDesc->Method.ParamCount)); 348243789Sdim 349243789Sdim /* Get the number of arguments to expect */ 350243789Sdim 351243789Sdim WalkState->ArgCount = MethodDesc->Method.ParamCount; 352243789Sdim return_ACPI_STATUS (AE_OK); 353243789Sdim } 354243789Sdim 355243789Sdim /* 356243789Sdim * Special handling if the name was not found during the lookup - 357243789Sdim * some NotFound cases are allowed 358243789Sdim */ 359243789Sdim if (Status == AE_NOT_FOUND) 360243789Sdim { 361243789Sdim /* 1) NotFound is ok during load pass 1/2 (allow forward references) */ 362243789Sdim 363243789Sdim if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) != 364243789Sdim ACPI_PARSE_EXECUTE) 365243789Sdim { 366243789Sdim Status = AE_OK; 367243789Sdim } 368243789Sdim 369243789Sdim /* 2) NotFound during a CondRefOf(x) is ok by definition */ 370243789Sdim 371243789Sdim else if (WalkState->Op->Common.AmlOpcode == AML_COND_REF_OF_OP) 372243789Sdim { 373243789Sdim Status = AE_OK; 374243789Sdim } 375243789Sdim 376243789Sdim /* 377243789Sdim * 3) NotFound while building a Package is ok at this point, we 378243789Sdim * may flag as an error later if slack mode is not enabled. 379243789Sdim * (Some ASL code depends on allowing this behavior) 380243789Sdim */ 381243789Sdim else if ((Arg->Common.Parent) && 382243789Sdim ((Arg->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 383243789Sdim (Arg->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) 384243789Sdim { 385243789Sdim Status = AE_OK; 386243789Sdim } 387243789Sdim } 388243789Sdim 389243789Sdim /* Final exception check (may have been changed from code above) */ 390243789Sdim 391243789Sdim if (ACPI_FAILURE (Status)) 392243789Sdim { 393243789Sdim ACPI_ERROR_NAMESPACE (Path, Status); 394243789Sdim 395243789Sdim if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == 396243789Sdim ACPI_PARSE_EXECUTE) 397243789Sdim { 398243789Sdim /* Report a control method execution error */ 399243789Sdim 400243789Sdim Status = AcpiDsMethodError (Status, WalkState); 401243789Sdim } 402243789Sdim } 403243789Sdim 404243789Sdim /* Save the namepath */ 405243789Sdim 406243789Sdim Arg->Common.Value.Name = Path; 407243789Sdim return_ACPI_STATUS (Status); 408243789Sdim} 409243789Sdim 410243789Sdim 411243789Sdim/******************************************************************************* 412243789Sdim * 413243789Sdim * FUNCTION: AcpiPsGetNextSimpleArg 414243789Sdim * 415243789Sdim * PARAMETERS: ParserState - Current parser state object 416243789Sdim * ArgType - The argument type (AML_*_ARG) 417243789Sdim * Arg - Where the argument is returned 418243789Sdim * 419243789Sdim * RETURN: None 420243789Sdim * 421243789Sdim * DESCRIPTION: Get the next simple argument (constant, string, or namestring) 422243789Sdim * 423243789Sdim ******************************************************************************/ 424243789Sdim 425243789Sdimvoid 426243789SdimAcpiPsGetNextSimpleArg ( 427243789Sdim ACPI_PARSE_STATE *ParserState, 428243789Sdim UINT32 ArgType, 429243789Sdim ACPI_PARSE_OBJECT *Arg) 430243789Sdim{ 431243789Sdim UINT32 Length; 432243789Sdim UINT16 Opcode; 433243789Sdim UINT8 *Aml = ParserState->Aml; 434243789Sdim 435243789Sdim 436243789Sdim ACPI_FUNCTION_TRACE_U32 (PsGetNextSimpleArg, ArgType); 437243789Sdim 438243789Sdim 439243789Sdim switch (ArgType) 440243789Sdim { 441243789Sdim case ARGP_BYTEDATA: 442243789Sdim 443243789Sdim /* Get 1 byte from the AML stream */ 444243789Sdim 445243789Sdim Opcode = AML_BYTE_OP; 446243789Sdim Arg->Common.Value.Integer = (UINT64) *Aml; 447243789Sdim Length = 1; 448243789Sdim break; 449243789Sdim 450243789Sdim case ARGP_WORDDATA: 451243789Sdim 452243789Sdim /* Get 2 bytes from the AML stream */ 453243789Sdim 454243789Sdim Opcode = AML_WORD_OP; 455243789Sdim ACPI_MOVE_16_TO_64 (&Arg->Common.Value.Integer, Aml); 456243789Sdim Length = 2; 457243789Sdim break; 458243789Sdim 459243789Sdim case ARGP_DWORDDATA: 460243789Sdim 461243789Sdim /* Get 4 bytes from the AML stream */ 462243789Sdim 463243789Sdim Opcode = AML_DWORD_OP; 464243789Sdim ACPI_MOVE_32_TO_64 (&Arg->Common.Value.Integer, Aml); 465243789Sdim Length = 4; 466243789Sdim break; 467243789Sdim 468243789Sdim case ARGP_QWORDDATA: 469243789Sdim 470243789Sdim /* Get 8 bytes from the AML stream */ 471243789Sdim 472243789Sdim Opcode = AML_QWORD_OP; 473243789Sdim ACPI_MOVE_64_TO_64 (&Arg->Common.Value.Integer, Aml); 474243789Sdim Length = 8; 475243789Sdim break; 476243789Sdim 477243789Sdim case ARGP_CHARLIST: 478243789Sdim 479243789Sdim /* Get a pointer to the string, point past the string */ 480243789Sdim 481243789Sdim Opcode = AML_STRING_OP; 482243789Sdim Arg->Common.Value.String = ACPI_CAST_PTR (char, Aml); 483243789Sdim 484243789Sdim /* Find the null terminator */ 485243789Sdim 486243789Sdim Length = 0; 487243789Sdim while (Aml[Length]) 488243789Sdim { 489243789Sdim Length++; 490243789Sdim } 491243789Sdim Length++; 492243789Sdim break; 493243789Sdim 494243789Sdim case ARGP_NAME: 495243789Sdim case ARGP_NAMESTRING: 496243789Sdim 497243789Sdim AcpiPsInitOp (Arg, AML_INT_NAMEPATH_OP); 498243789Sdim Arg->Common.Value.Name = AcpiPsGetNextNamestring (ParserState); 499243789Sdim return_VOID; 500243789Sdim 501243789Sdim default: 502243789Sdim 503243789Sdim ACPI_ERROR ((AE_INFO, "Invalid ArgType 0x%X", ArgType)); 504243789Sdim return_VOID; 505243789Sdim } 506243789Sdim 507243789Sdim AcpiPsInitOp (Arg, Opcode); 508243789Sdim ParserState->Aml += Length; 509243789Sdim return_VOID; 510243789Sdim} 511243789Sdim 512243789Sdim 513243789Sdim/******************************************************************************* 514243789Sdim * 515243789Sdim * FUNCTION: AcpiPsGetNextField 516243789Sdim * 517243789Sdim * PARAMETERS: ParserState - Current parser state object 518243789Sdim * 519243789Sdim * RETURN: A newly allocated FIELD op 520243789Sdim * 521243789Sdim * DESCRIPTION: Get next field (NamedField, ReservedField, or AccessField) 522243789Sdim * 523243789Sdim ******************************************************************************/ 524243789Sdim 525243789Sdimstatic ACPI_PARSE_OBJECT * 526243789SdimAcpiPsGetNextField ( 527243789Sdim ACPI_PARSE_STATE *ParserState) 528243789Sdim{ 529243789Sdim UINT32 AmlOffset; 530243789Sdim ACPI_PARSE_OBJECT *Field; 531243789Sdim ACPI_PARSE_OBJECT *Arg = NULL; 532243789Sdim UINT16 Opcode; 533243789Sdim UINT32 Name; 534243789Sdim UINT8 AccessType; 535243789Sdim UINT8 AccessAttribute; 536243789Sdim UINT8 AccessLength; 537249423Sdim UINT32 PkgLength; 538243789Sdim UINT8 *PkgEnd; 539249423Sdim UINT32 BufferLength; 540243789Sdim 541243789Sdim 542243789Sdim ACPI_FUNCTION_TRACE (PsGetNextField); 543243789Sdim 544243789Sdim 545243789Sdim AmlOffset = (UINT32) ACPI_PTR_DIFF ( 546243789Sdim ParserState->Aml, ParserState->AmlStart); 547243789Sdim 548249423Sdim /* Determine field type */ 549243789Sdim 550249423Sdim switch (ACPI_GET8 (ParserState->Aml)) 551243789Sdim { 552243789Sdim case AML_FIELD_OFFSET_OP: 553243789Sdim 554243789Sdim Opcode = AML_INT_RESERVEDFIELD_OP; 555243789Sdim ParserState->Aml++; 556243789Sdim break; 557243789Sdim 558243789Sdim case AML_FIELD_ACCESS_OP: 559243789Sdim 560243789Sdim Opcode = AML_INT_ACCESSFIELD_OP; 561243789Sdim ParserState->Aml++; 562243789Sdim break; 563243789Sdim 564243789Sdim case AML_FIELD_CONNECTION_OP: 565243789Sdim 566243789Sdim Opcode = AML_INT_CONNECTION_OP; 567243789Sdim ParserState->Aml++; 568243789Sdim break; 569243789Sdim 570243789Sdim case AML_FIELD_EXT_ACCESS_OP: 571243789Sdim 572243789Sdim Opcode = AML_INT_EXTACCESSFIELD_OP; 573243789Sdim ParserState->Aml++; 574243789Sdim break; 575243789Sdim 576243789Sdim default: 577243789Sdim 578243789Sdim Opcode = AML_INT_NAMEDFIELD_OP; 579243789Sdim break; 580243789Sdim } 581243789Sdim 582243789Sdim /* Allocate a new field op */ 583243789Sdim 584243789Sdim Field = AcpiPsAllocOp (Opcode); 585243789Sdim if (!Field) 586243789Sdim { 587243789Sdim return_PTR (NULL); 588243789Sdim } 589243789Sdim 590243789Sdim Field->Common.AmlOffset = AmlOffset; 591243789Sdim 592243789Sdim /* Decode the field type */ 593243789Sdim 594243789Sdim switch (Opcode) 595243789Sdim { 596243789Sdim case AML_INT_NAMEDFIELD_OP: 597243789Sdim 598243789Sdim /* Get the 4-character name */ 599243789Sdim 600243789Sdim ACPI_MOVE_32_TO_32 (&Name, ParserState->Aml); 601243789Sdim AcpiPsSetName (Field, Name); 602243789Sdim ParserState->Aml += ACPI_NAME_SIZE; 603243789Sdim 604243789Sdim /* Get the length which is encoded as a package length */ 605 606 Field->Common.Value.Size = AcpiPsGetNextPackageLength (ParserState); 607 break; 608 609 610 case AML_INT_RESERVEDFIELD_OP: 611 612 /* Get the length which is encoded as a package length */ 613 614 Field->Common.Value.Size = AcpiPsGetNextPackageLength (ParserState); 615 break; 616 617 618 case AML_INT_ACCESSFIELD_OP: 619 case AML_INT_EXTACCESSFIELD_OP: 620 621 /* 622 * Get AccessType and AccessAttrib and merge into the field Op 623 * AccessType is first operand, AccessAttribute is second. stuff 624 * these bytes into the node integer value for convenience. 625 */ 626 627 /* Get the two bytes (Type/Attribute) */ 628 629 AccessType = ACPI_GET8 (ParserState->Aml); 630 ParserState->Aml++; 631 AccessAttribute = ACPI_GET8 (ParserState->Aml); 632 ParserState->Aml++; 633 634 Field->Common.Value.Integer = (UINT8) AccessType; 635 Field->Common.Value.Integer |= (UINT16) (AccessAttribute << 8); 636 637 /* This opcode has a third byte, AccessLength */ 638 639 if (Opcode == AML_INT_EXTACCESSFIELD_OP) 640 { 641 AccessLength = ACPI_GET8 (ParserState->Aml); 642 ParserState->Aml++; 643 644 Field->Common.Value.Integer |= (UINT32) (AccessLength << 16); 645 } 646 break; 647 648 649 case AML_INT_CONNECTION_OP: 650 651 /* 652 * Argument for Connection operator can be either a Buffer 653 * (resource descriptor), or a NameString. 654 */ 655 if (ACPI_GET8 (ParserState->Aml) == AML_BUFFER_OP) 656 { 657 ParserState->Aml++; 658 659 PkgEnd = ParserState->Aml; 660 PkgLength = AcpiPsGetNextPackageLength (ParserState); 661 PkgEnd += PkgLength; 662 663 if (ParserState->Aml < PkgEnd) 664 { 665 /* Non-empty list */ 666 667 Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP); 668 if (!Arg) 669 { 670 AcpiPsFreeOp (Field); 671 return_PTR (NULL); 672 } 673 674 /* Get the actual buffer length argument */ 675 676 Opcode = ACPI_GET8 (ParserState->Aml); 677 ParserState->Aml++; 678 679 switch (Opcode) 680 { 681 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ 682 683 BufferLength = ACPI_GET8 (ParserState->Aml); 684 ParserState->Aml += 1; 685 break; 686 687 case AML_WORD_OP: /* AML_WORDDATA_ARG */ 688 689 BufferLength = ACPI_GET16 (ParserState->Aml); 690 ParserState->Aml += 2; 691 break; 692 693 case AML_DWORD_OP: /* AML_DWORDATA_ARG */ 694 695 BufferLength = ACPI_GET32 (ParserState->Aml); 696 ParserState->Aml += 4; 697 break; 698 699 default: 700 701 BufferLength = 0; 702 break; 703 } 704 705 /* Fill in bytelist data */ 706 707 Arg->Named.Value.Size = BufferLength; 708 Arg->Named.Data = ParserState->Aml; 709 } 710 711 /* Skip to End of byte data */ 712 713 ParserState->Aml = PkgEnd; 714 } 715 else 716 { 717 Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); 718 if (!Arg) 719 { 720 AcpiPsFreeOp (Field); 721 return_PTR (NULL); 722 } 723 724 /* Get the Namestring argument */ 725 726 Arg->Common.Value.Name = AcpiPsGetNextNamestring (ParserState); 727 } 728 729 /* Link the buffer/namestring to parent (CONNECTION_OP) */ 730 731 AcpiPsAppendArg (Field, Arg); 732 break; 733 734 735 default: 736 737 /* Opcode was set in previous switch */ 738 break; 739 } 740 741 return_PTR (Field); 742} 743 744 745/******************************************************************************* 746 * 747 * FUNCTION: AcpiPsGetNextArg 748 * 749 * PARAMETERS: WalkState - Current state 750 * ParserState - Current parser state object 751 * ArgType - The argument type (AML_*_ARG) 752 * ReturnArg - Where the next arg is returned 753 * 754 * RETURN: Status, and an op object containing the next argument. 755 * 756 * DESCRIPTION: Get next argument (including complex list arguments that require 757 * pushing the parser stack) 758 * 759 ******************************************************************************/ 760 761ACPI_STATUS 762AcpiPsGetNextArg ( 763 ACPI_WALK_STATE *WalkState, 764 ACPI_PARSE_STATE *ParserState, 765 UINT32 ArgType, 766 ACPI_PARSE_OBJECT **ReturnArg) 767{ 768 ACPI_PARSE_OBJECT *Arg = NULL; 769 ACPI_PARSE_OBJECT *Prev = NULL; 770 ACPI_PARSE_OBJECT *Field; 771 UINT32 Subop; 772 ACPI_STATUS Status = AE_OK; 773 774 775 ACPI_FUNCTION_TRACE_PTR (PsGetNextArg, ParserState); 776 777 778 switch (ArgType) 779 { 780 case ARGP_BYTEDATA: 781 case ARGP_WORDDATA: 782 case ARGP_DWORDDATA: 783 case ARGP_CHARLIST: 784 case ARGP_NAME: 785 case ARGP_NAMESTRING: 786 787 /* Constants, strings, and namestrings are all the same size */ 788 789 Arg = AcpiPsAllocOp (AML_BYTE_OP); 790 if (!Arg) 791 { 792 return_ACPI_STATUS (AE_NO_MEMORY); 793 } 794 AcpiPsGetNextSimpleArg (ParserState, ArgType, Arg); 795 break; 796 797 case ARGP_PKGLENGTH: 798 799 /* Package length, nothing returned */ 800 801 ParserState->PkgEnd = AcpiPsGetNextPackageEnd (ParserState); 802 break; 803 804 case ARGP_FIELDLIST: 805 806 if (ParserState->Aml < ParserState->PkgEnd) 807 { 808 /* Non-empty list */ 809 810 while (ParserState->Aml < ParserState->PkgEnd) 811 { 812 Field = AcpiPsGetNextField (ParserState); 813 if (!Field) 814 { 815 return_ACPI_STATUS (AE_NO_MEMORY); 816 } 817 818 if (Prev) 819 { 820 Prev->Common.Next = Field; 821 } 822 else 823 { 824 Arg = Field; 825 } 826 Prev = Field; 827 } 828 829 /* Skip to End of byte data */ 830 831 ParserState->Aml = ParserState->PkgEnd; 832 } 833 break; 834 835 case ARGP_BYTELIST: 836 837 if (ParserState->Aml < ParserState->PkgEnd) 838 { 839 /* Non-empty list */ 840 841 Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP); 842 if (!Arg) 843 { 844 return_ACPI_STATUS (AE_NO_MEMORY); 845 } 846 847 /* Fill in bytelist data */ 848 849 Arg->Common.Value.Size = (UINT32) 850 ACPI_PTR_DIFF (ParserState->PkgEnd, ParserState->Aml); 851 Arg->Named.Data = ParserState->Aml; 852 853 /* Skip to End of byte data */ 854 855 ParserState->Aml = ParserState->PkgEnd; 856 } 857 break; 858 859 case ARGP_TARGET: 860 case ARGP_SUPERNAME: 861 case ARGP_SIMPLENAME: 862 863 Subop = AcpiPsPeekOpcode (ParserState); 864 if (Subop == 0 || 865 AcpiPsIsLeadingChar (Subop) || 866 ACPI_IS_ROOT_PREFIX (Subop) || 867 ACPI_IS_PARENT_PREFIX (Subop)) 868 { 869 /* NullName or NameString */ 870 871 Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); 872 if (!Arg) 873 { 874 return_ACPI_STATUS (AE_NO_MEMORY); 875 } 876 877 /* To support SuperName arg of Unload */ 878 879 if (WalkState->Opcode == AML_UNLOAD_OP) 880 { 881 Status = AcpiPsGetNextNamepath (WalkState, ParserState, Arg, 1); 882 883 /* 884 * If the SuperName arg of Unload is a method call, 885 * we have restored the AML pointer, just free this Arg 886 */ 887 if (Arg->Common.AmlOpcode == AML_INT_METHODCALL_OP) 888 { 889 AcpiPsFreeOp (Arg); 890 Arg = NULL; 891 } 892 } 893 else 894 { 895 Status = AcpiPsGetNextNamepath (WalkState, ParserState, Arg, 0); 896 } 897 } 898 else 899 { 900 /* Single complex argument, nothing returned */ 901 902 WalkState->ArgCount = 1; 903 } 904 break; 905 906 case ARGP_DATAOBJ: 907 case ARGP_TERMARG: 908 909 /* Single complex argument, nothing returned */ 910 911 WalkState->ArgCount = 1; 912 break; 913 914 case ARGP_DATAOBJLIST: 915 case ARGP_TERMLIST: 916 case ARGP_OBJLIST: 917 918 if (ParserState->Aml < ParserState->PkgEnd) 919 { 920 /* Non-empty list of variable arguments, nothing returned */ 921 922 WalkState->ArgCount = ACPI_VAR_ARGS; 923 } 924 break; 925 926 default: 927 928 ACPI_ERROR ((AE_INFO, "Invalid ArgType: 0x%X", ArgType)); 929 Status = AE_AML_OPERAND_TYPE; 930 break; 931 } 932 933 *ReturnArg = Arg; 934 return_ACPI_STATUS (Status); 935} 936