1118611Snjl/****************************************************************************** 2118611Snjl * 3118611Snjl * Module Name: aslopcode - AML opcode generation 4118611Snjl * 5118611Snjl *****************************************************************************/ 6118611Snjl 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9118611Snjl * All rights reserved. 10118611Snjl * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25118611Snjl * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29118611Snjl * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43118611Snjl 44151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45118611Snjl#include "aslcompiler.y.h" 46193529Sjkim#include <contrib/dev/acpica/include/amlcode.h> 47118611Snjl 48118611Snjl#define _COMPONENT ACPI_COMPILER 49118611Snjl ACPI_MODULE_NAME ("aslopcodes") 50118611Snjl 51118611Snjl 52151937Sjkim/* Local prototypes */ 53151937Sjkim 54151937Sjkimstatic void 55151937SjkimOpcDoAccessAs ( 56151937Sjkim ACPI_PARSE_OBJECT *Op); 57151937Sjkim 58151937Sjkimstatic void 59228110SjkimOpcDoConnection ( 60228110Sjkim ACPI_PARSE_OBJECT *Op); 61228110Sjkim 62228110Sjkimstatic void 63151937SjkimOpcDoUnicode ( 64151937Sjkim ACPI_PARSE_OBJECT *Op); 65151937Sjkim 66151937Sjkimstatic void 67151937SjkimOpcDoEisaId ( 68151937Sjkim ACPI_PARSE_OBJECT *Op); 69151937Sjkim 70151937Sjkimstatic void 71151937SjkimOpcDoUuId ( 72151937Sjkim ACPI_PARSE_OBJECT *Op); 73151937Sjkim 74151937Sjkim 75118611Snjl/******************************************************************************* 76118611Snjl * 77151937Sjkim * FUNCTION: OpcAmlOpcodeUpdateWalk 78151937Sjkim * 79151937Sjkim * PARAMETERS: ASL_WALK_CALLBACK 80151937Sjkim * 81151937Sjkim * RETURN: Status 82151937Sjkim * 83151937Sjkim * DESCRIPTION: Opcode update walk, ascending callback 84151937Sjkim * 85151937Sjkim ******************************************************************************/ 86151937Sjkim 87151937SjkimACPI_STATUS 88151937SjkimOpcAmlOpcodeUpdateWalk ( 89151937Sjkim ACPI_PARSE_OBJECT *Op, 90151937Sjkim UINT32 Level, 91151937Sjkim void *Context) 92151937Sjkim{ 93151937Sjkim 94151937Sjkim /* 95151937Sjkim * Handle the Package() case where the actual opcode cannot be determined 96151937Sjkim * until the PackageLength operand has been folded and minimized. 97151937Sjkim * (PackageOp versus VarPackageOp) 98151937Sjkim * 99151937Sjkim * This is (as of ACPI 3.0) the only case where the AML opcode can change 100151937Sjkim * based upon the value of a parameter. 101151937Sjkim * 102151937Sjkim * The parser always inserts a VarPackage opcode, which can possibly be 103151937Sjkim * optimized to a Package opcode. 104151937Sjkim */ 105151937Sjkim if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE) 106151937Sjkim { 107151937Sjkim OpnDoPackage (Op); 108151937Sjkim } 109151937Sjkim 110151937Sjkim return (AE_OK); 111151937Sjkim} 112151937Sjkim 113151937Sjkim 114151937Sjkim/******************************************************************************* 115151937Sjkim * 116118611Snjl * FUNCTION: OpcAmlOpcodeWalk 117118611Snjl * 118118611Snjl * PARAMETERS: ASL_WALK_CALLBACK 119118611Snjl * 120118611Snjl * RETURN: Status 121118611Snjl * 122118611Snjl * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML 123118611Snjl * operands. 124118611Snjl * 125118611Snjl ******************************************************************************/ 126118611Snjl 127118611SnjlACPI_STATUS 128118611SnjlOpcAmlOpcodeWalk ( 129118611Snjl ACPI_PARSE_OBJECT *Op, 130118611Snjl UINT32 Level, 131118611Snjl void *Context) 132118611Snjl{ 133118611Snjl 134118611Snjl TotalParseNodes++; 135118611Snjl 136118611Snjl OpcGenerateAmlOpcode (Op); 137118611Snjl OpnGenerateAmlOperands (Op); 138118611Snjl return (AE_OK); 139118611Snjl} 140118611Snjl 141118611Snjl 142118611Snjl/******************************************************************************* 143118611Snjl * 144118611Snjl * FUNCTION: OpcGetIntegerWidth 145118611Snjl * 146118611Snjl * PARAMETERS: Op - DEFINITION BLOCK op 147118611Snjl * 148118611Snjl * RETURN: none 149118611Snjl * 150118611Snjl * DESCRIPTION: Extract integer width from the table revision 151118611Snjl * 152118611Snjl ******************************************************************************/ 153118611Snjl 154118611Snjlvoid 155118611SnjlOpcGetIntegerWidth ( 156118611Snjl ACPI_PARSE_OBJECT *Op) 157118611Snjl{ 158118611Snjl ACPI_PARSE_OBJECT *Child; 159118611Snjl 160151937Sjkim 161118611Snjl if (!Op) 162118611Snjl { 163118611Snjl return; 164118611Snjl } 165118611Snjl 166151937Sjkim if (Gbl_RevisionOverride) 167151937Sjkim { 168151937Sjkim AcpiUtSetIntegerWidth (Gbl_RevisionOverride); 169151937Sjkim } 170151937Sjkim else 171151937Sjkim { 172151937Sjkim Child = Op->Asl.Child; 173151937Sjkim Child = Child->Asl.Next; 174151937Sjkim Child = Child->Asl.Next; 175118611Snjl 176151937Sjkim /* Use the revision to set the integer width */ 177118611Snjl 178151937Sjkim AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer); 179151937Sjkim } 180118611Snjl} 181118611Snjl 182118611Snjl 183118611Snjl/******************************************************************************* 184118611Snjl * 185118611Snjl * FUNCTION: OpcSetOptimalIntegerSize 186118611Snjl * 187118611Snjl * PARAMETERS: Op - A parse tree node 188118611Snjl * 189241973Sjkim * RETURN: Integer width, in bytes. Also sets the node AML opcode to the 190118611Snjl * optimal integer AML prefix opcode. 191118611Snjl * 192241973Sjkim * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading 193118611Snjl * zeros can be truncated to squeeze the integer into the 194118611Snjl * minimal number of AML bytes. 195118611Snjl * 196118611Snjl ******************************************************************************/ 197118611Snjl 198118611SnjlUINT32 199118611SnjlOpcSetOptimalIntegerSize ( 200118611Snjl ACPI_PARSE_OBJECT *Op) 201118611Snjl{ 202118611Snjl 203151937Sjkim#if 0 204151937Sjkim /* 205151937Sjkim * TBD: - we don't want to optimize integers in the block header, but the 206151937Sjkim * code below does not work correctly. 207151937Sjkim */ 208138287Smarks if (Op->Asl.Parent && 209138287Smarks Op->Asl.Parent->Asl.Parent && 210306536Sjkim (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK)) 211138287Smarks { 212241973Sjkim return (0); 213138287Smarks } 214151937Sjkim#endif 215138287Smarks 216118611Snjl /* 217118611Snjl * Check for the special AML integers first - Zero, One, Ones. 218118611Snjl * These are single-byte opcodes that are the smallest possible 219118611Snjl * representation of an integer. 220118611Snjl * 221118611Snjl * This optimization is optional. 222118611Snjl */ 223118611Snjl if (Gbl_IntegerOptimizationFlag) 224118611Snjl { 225118611Snjl switch (Op->Asl.Value.Integer) 226118611Snjl { 227118611Snjl case 0: 228118611Snjl 229118611Snjl Op->Asl.AmlOpcode = AML_ZERO_OP; 230151937Sjkim AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, 231151937Sjkim Op, "Zero"); 232241973Sjkim return (1); 233118611Snjl 234118611Snjl case 1: 235118611Snjl 236118611Snjl Op->Asl.AmlOpcode = AML_ONE_OP; 237151937Sjkim AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, 238151937Sjkim Op, "One"); 239241973Sjkim return (1); 240118611Snjl 241118611Snjl case ACPI_UINT32_MAX: 242118611Snjl 243118611Snjl /* Check for table integer width (32 or 64) */ 244118611Snjl 245118611Snjl if (AcpiGbl_IntegerByteWidth == 4) 246118611Snjl { 247118611Snjl Op->Asl.AmlOpcode = AML_ONES_OP; 248151937Sjkim AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, 249151937Sjkim Op, "Ones"); 250241973Sjkim return (1); 251118611Snjl } 252118611Snjl break; 253118611Snjl 254202771Sjkim case ACPI_UINT64_MAX: 255118611Snjl 256118611Snjl /* Check for table integer width (32 or 64) */ 257118611Snjl 258118611Snjl if (AcpiGbl_IntegerByteWidth == 8) 259118611Snjl { 260118611Snjl Op->Asl.AmlOpcode = AML_ONES_OP; 261151937Sjkim AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION, 262151937Sjkim Op, "Ones"); 263241973Sjkim return (1); 264118611Snjl } 265118611Snjl break; 266118611Snjl 267118611Snjl default: 268250838Sjkim 269118611Snjl break; 270118611Snjl } 271118611Snjl } 272118611Snjl 273118611Snjl /* Find the best fit using the various AML integer prefixes */ 274118611Snjl 275118611Snjl if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX) 276118611Snjl { 277118611Snjl Op->Asl.AmlOpcode = AML_BYTE_OP; 278241973Sjkim return (1); 279118611Snjl } 280306536Sjkim 281118611Snjl if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX) 282118611Snjl { 283118611Snjl Op->Asl.AmlOpcode = AML_WORD_OP; 284241973Sjkim return (2); 285118611Snjl } 286306536Sjkim 287118611Snjl if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX) 288118611Snjl { 289118611Snjl Op->Asl.AmlOpcode = AML_DWORD_OP; 290241973Sjkim return (4); 291118611Snjl } 292118611Snjl else 293118611Snjl { 294151937Sjkim if (AcpiGbl_IntegerByteWidth == 4) 295151937Sjkim { 296151937Sjkim AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH, 297151937Sjkim Op, NULL); 298151937Sjkim 299151937Sjkim if (!Gbl_IgnoreErrors) 300151937Sjkim { 301151937Sjkim /* Truncate the integer to 32-bit */ 302151937Sjkim Op->Asl.AmlOpcode = AML_DWORD_OP; 303241973Sjkim return (4); 304151937Sjkim } 305151937Sjkim } 306151937Sjkim 307118611Snjl Op->Asl.AmlOpcode = AML_QWORD_OP; 308241973Sjkim return (8); 309118611Snjl } 310118611Snjl} 311118611Snjl 312118611Snjl 313118611Snjl/******************************************************************************* 314118611Snjl * 315118611Snjl * FUNCTION: OpcDoAccessAs 316118611Snjl * 317118611Snjl * PARAMETERS: Op - Parse node 318118611Snjl * 319118611Snjl * RETURN: None 320118611Snjl * 321118611Snjl * DESCRIPTION: Implement the ACCESS_AS ASL keyword. 322118611Snjl * 323118611Snjl ******************************************************************************/ 324118611Snjl 325151937Sjkimstatic void 326118611SnjlOpcDoAccessAs ( 327151937Sjkim ACPI_PARSE_OBJECT *Op) 328118611Snjl{ 329228110Sjkim ACPI_PARSE_OBJECT *TypeOp; 330228110Sjkim ACPI_PARSE_OBJECT *AttribOp; 331228110Sjkim ACPI_PARSE_OBJECT *LengthOp; 332228110Sjkim UINT8 Attribute; 333118611Snjl 334118611Snjl 335118611Snjl Op->Asl.AmlOpcodeLength = 1; 336228110Sjkim TypeOp = Op->Asl.Child; 337118611Snjl 338118611Snjl /* First child is the access type */ 339118611Snjl 340228110Sjkim TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 341228110Sjkim TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 342118611Snjl 343118611Snjl /* Second child is the optional access attribute */ 344118611Snjl 345228110Sjkim AttribOp = TypeOp->Asl.Next; 346228110Sjkim if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 347118611Snjl { 348228110Sjkim AttribOp->Asl.Value.Integer = 0; 349118611Snjl } 350306536Sjkim 351228110Sjkim AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 352228110Sjkim AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 353228110Sjkim 354228110Sjkim /* Only a few AccessAttributes support AccessLength */ 355228110Sjkim 356228110Sjkim Attribute = (UINT8) AttribOp->Asl.Value.Integer; 357228110Sjkim if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) && 358228110Sjkim (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) && 359228110Sjkim (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS)) 360228110Sjkim { 361228110Sjkim return; 362228110Sjkim } 363228110Sjkim 364228110Sjkim Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP; 365228110Sjkim 366228110Sjkim /* 367228110Sjkim * Child of Attributes is the AccessLength (required for Multibyte, 368228110Sjkim * RawBytes, RawProcess.) 369228110Sjkim */ 370228110Sjkim LengthOp = AttribOp->Asl.Child; 371228110Sjkim if (!LengthOp) 372228110Sjkim { 373228110Sjkim return; 374228110Sjkim } 375228110Sjkim 376228110Sjkim /* TBD: probably can remove */ 377228110Sjkim 378228110Sjkim if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 379228110Sjkim { 380228110Sjkim LengthOp->Asl.Value.Integer = 16; 381228110Sjkim } 382228110Sjkim 383228110Sjkim LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 384228110Sjkim LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 385118611Snjl} 386118611Snjl 387118611Snjl 388118611Snjl/******************************************************************************* 389118611Snjl * 390228110Sjkim * FUNCTION: OpcDoConnection 391228110Sjkim * 392228110Sjkim * PARAMETERS: Op - Parse node 393228110Sjkim * 394228110Sjkim * RETURN: None 395228110Sjkim * 396228110Sjkim * DESCRIPTION: Implement the Connection ASL keyword. 397228110Sjkim * 398228110Sjkim ******************************************************************************/ 399228110Sjkim 400228110Sjkimstatic void 401228110SjkimOpcDoConnection ( 402228110Sjkim ACPI_PARSE_OBJECT *Op) 403228110Sjkim{ 404228110Sjkim ASL_RESOURCE_NODE *Rnode; 405228110Sjkim ACPI_PARSE_OBJECT *BufferOp; 406228110Sjkim ACPI_PARSE_OBJECT *BufferLengthOp; 407228110Sjkim ACPI_PARSE_OBJECT *BufferDataOp; 408281075Sdim ASL_RESOURCE_INFO Info; 409228110Sjkim UINT8 State; 410228110Sjkim 411228110Sjkim 412228110Sjkim Op->Asl.AmlOpcodeLength = 1; 413228110Sjkim 414228110Sjkim if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP) 415228110Sjkim { 416228110Sjkim return; 417228110Sjkim } 418228110Sjkim 419228110Sjkim BufferOp = Op->Asl.Child; 420228110Sjkim BufferLengthOp = BufferOp->Asl.Child; 421228110Sjkim BufferDataOp = BufferLengthOp->Asl.Next; 422228110Sjkim 423281075Sdim Info.DescriptorTypeOp = BufferDataOp->Asl.Next; 424281075Sdim Info.CurrentByteOffset = 0; 425228110Sjkim State = ACPI_RSTATE_NORMAL; 426281075Sdim Rnode = RsDoOneResourceDescriptor (&Info, &State); 427228110Sjkim if (!Rnode) 428228110Sjkim { 429228110Sjkim return; /* error */ 430228110Sjkim } 431228110Sjkim 432228110Sjkim /* 433228110Sjkim * Transform the nodes into the following 434228110Sjkim * 435228110Sjkim * Op -> AML_BUFFER_OP 436228110Sjkim * First Child -> BufferLength 437228110Sjkim * Second Child -> Descriptor Buffer (raw byte data) 438228110Sjkim */ 439306536Sjkim BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER; 440306536Sjkim BufferOp->Asl.AmlOpcode = AML_BUFFER_OP; 441306536Sjkim BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC; 442228110Sjkim UtSetParseOpName (BufferOp); 443228110Sjkim 444306536Sjkim BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; 445228110Sjkim BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength; 446228110Sjkim (void) OpcSetOptimalIntegerSize (BufferLengthOp); 447228110Sjkim UtSetParseOpName (BufferLengthOp); 448228110Sjkim 449306536Sjkim BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 450306536Sjkim BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN; 451306536Sjkim BufferDataOp->Asl.AmlOpcodeLength = 0; 452306536Sjkim BufferDataOp->Asl.AmlLength = Rnode->BufferLength; 453306536Sjkim BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode; 454228110Sjkim UtSetParseOpName (BufferDataOp); 455228110Sjkim} 456228110Sjkim 457228110Sjkim 458228110Sjkim/******************************************************************************* 459228110Sjkim * 460118611Snjl * FUNCTION: OpcDoUnicode 461118611Snjl * 462118611Snjl * PARAMETERS: Op - Parse node 463118611Snjl * 464118611Snjl * RETURN: None 465118611Snjl * 466118611Snjl * DESCRIPTION: Implement the UNICODE ASL "macro". Convert the input string 467241973Sjkim * to a unicode buffer. There is no Unicode AML opcode. 468118611Snjl * 469118611Snjl * Note: The Unicode string is 16 bits per character, no leading signature, 470118611Snjl * with a 16-bit terminating NULL. 471118611Snjl * 472118611Snjl ******************************************************************************/ 473118611Snjl 474151937Sjkimstatic void 475118611SnjlOpcDoUnicode ( 476151937Sjkim ACPI_PARSE_OBJECT *Op) 477118611Snjl{ 478151937Sjkim ACPI_PARSE_OBJECT *InitializerOp; 479151937Sjkim UINT32 Length; 480151937Sjkim UINT32 Count; 481151937Sjkim UINT32 i; 482151937Sjkim UINT8 *AsciiString; 483151937Sjkim UINT16 *UnicodeString; 484151937Sjkim ACPI_PARSE_OBJECT *BufferLengthOp; 485118611Snjl 486118611Snjl 487118611Snjl /* Change op into a buffer object */ 488118611Snjl 489118611Snjl Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; 490118611Snjl Op->Asl.ParseOpcode = PARSEOP_BUFFER; 491118611Snjl UtSetParseOpName (Op); 492118611Snjl 493118611Snjl /* Buffer Length is first, followed by the string */ 494118611Snjl 495118611Snjl BufferLengthOp = Op->Asl.Child; 496118611Snjl InitializerOp = BufferLengthOp->Asl.Next; 497118611Snjl 498118611Snjl AsciiString = (UINT8 *) InitializerOp->Asl.Value.String; 499118611Snjl 500118611Snjl /* Create a new buffer for the Unicode string */ 501118611Snjl 502118611Snjl Count = strlen (InitializerOp->Asl.Value.String) + 1; 503118611Snjl Length = Count * sizeof (UINT16); 504118611Snjl UnicodeString = UtLocalCalloc (Length); 505118611Snjl 506118611Snjl /* Convert to Unicode string (including null terminator) */ 507118611Snjl 508118611Snjl for (i = 0; i < Count; i++) 509118611Snjl { 510118611Snjl UnicodeString[i] = (UINT16) AsciiString[i]; 511118611Snjl } 512118611Snjl 513118611Snjl /* 514118611Snjl * Just set the buffer size node to be the buffer length, regardless 515118611Snjl * of whether it was previously an integer or a default_arg placeholder 516118611Snjl */ 517306536Sjkim BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; 518306536Sjkim BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP; 519118611Snjl BufferLengthOp->Asl.Value.Integer = Length; 520118611Snjl UtSetParseOpName (BufferLengthOp); 521118611Snjl 522118611Snjl (void) OpcSetOptimalIntegerSize (BufferLengthOp); 523118611Snjl 524118611Snjl /* The Unicode string is a raw data buffer */ 525118611Snjl 526306536Sjkim InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString; 527306536Sjkim InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; 528306536Sjkim InitializerOp->Asl.AmlLength = Length; 529306536Sjkim InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 530306536Sjkim InitializerOp->Asl.Child = NULL; 531118611Snjl UtSetParseOpName (InitializerOp); 532118611Snjl} 533118611Snjl 534118611Snjl 535118611Snjl/******************************************************************************* 536118611Snjl * 537118611Snjl * FUNCTION: OpcDoEisaId 538118611Snjl * 539118611Snjl * PARAMETERS: Op - Parse node 540118611Snjl * 541118611Snjl * RETURN: None 542118611Snjl * 543241973Sjkim * DESCRIPTION: Convert a string EISA ID to numeric representation. See the 544241973Sjkim * Pnp BIOS Specification for details. Here is an excerpt: 545118611Snjl * 546118611Snjl * A seven character ASCII representation of the product 547241973Sjkim * identifier compressed into a 32-bit identifier. The seven 548118611Snjl * character ID consists of a three character manufacturer code, 549118611Snjl * a three character hexadecimal product identifier, and a one 550241973Sjkim * character hexadecimal revision number. The manufacturer code 551118611Snjl * is a 3 uppercase character code that is compressed into 3 5-bit 552118611Snjl * values as follows: 553118611Snjl * 1) Find hex ASCII value for each letter 554118611Snjl * 2) Subtract 40h from each ASCII value 555241973Sjkim * 3) Retain 5 least significant bits for each letter by 556118611Snjl * discarding upper 3 bits because they are always 0. 557118611Snjl * 4) Compressed code = concatenate 0 and the 3 5-bit values 558118611Snjl * 559118611Snjl * The format of the compressed product identifier is as follows: 560118611Snjl * Byte 0: Bit 7 - Reserved (0) 561118611Snjl * Bits 6-2: - 1st character of compressed mfg code 562118611Snjl * Bits 1-0 - Upper 2 bits of 2nd character of mfg code 563118611Snjl * Byte 1: Bits 7-5 - Lower 3 bits of 2nd character of mfg code 564118611Snjl * Bits 4-0 - 3rd character of mfg code 565118611Snjl * Byte 2: Bits 7-4 - 1st hex digit of product number 566118611Snjl * Bits 3-0 - 2nd hex digit of product number 567118611Snjl * Byte 3: Bits 7-4 - 3st hex digit of product number 568118611Snjl * Bits 3-0 - Hex digit of the revision number 569118611Snjl * 570118611Snjl ******************************************************************************/ 571118611Snjl 572151937Sjkimstatic void 573118611SnjlOpcDoEisaId ( 574118611Snjl ACPI_PARSE_OBJECT *Op) 575118611Snjl{ 576118611Snjl UINT32 EisaId = 0; 577118611Snjl UINT32 BigEndianId; 578118611Snjl char *InString; 579118611Snjl ACPI_STATUS Status = AE_OK; 580193529Sjkim UINT32 i; 581118611Snjl 582118611Snjl 583118611Snjl InString = (char *) Op->Asl.Value.String; 584118611Snjl 585118611Snjl /* 586118611Snjl * The EISAID string must be exactly 7 characters and of the form 587151937Sjkim * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001") 588118611Snjl */ 589306536Sjkim if (strlen (InString) != 7) 590118611Snjl { 591118611Snjl Status = AE_BAD_PARAMETER; 592118611Snjl } 593118611Snjl else 594118611Snjl { 595118611Snjl /* Check all 7 characters for correct format */ 596118611Snjl 597118611Snjl for (i = 0; i < 7; i++) 598118611Snjl { 599138287Smarks /* First 3 characters must be uppercase letters */ 600118611Snjl 601118611Snjl if (i < 3) 602118611Snjl { 603202771Sjkim if (!isupper ((int) InString[i])) 604118611Snjl { 605118611Snjl Status = AE_BAD_PARAMETER; 606118611Snjl } 607118611Snjl } 608118611Snjl 609118611Snjl /* Last 4 characters must be hex digits */ 610118611Snjl 611202771Sjkim else if (!isxdigit ((int) InString[i])) 612118611Snjl { 613118611Snjl Status = AE_BAD_PARAMETER; 614118611Snjl } 615118611Snjl } 616118611Snjl } 617118611Snjl 618118611Snjl if (ACPI_FAILURE (Status)) 619118611Snjl { 620118611Snjl AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String); 621118611Snjl } 622118611Snjl else 623118611Snjl { 624118611Snjl /* Create ID big-endian first (bits are contiguous) */ 625118611Snjl 626167802Sjkim BigEndianId = 627212761Sjkim (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 | 628212761Sjkim (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 | 629212761Sjkim (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 | 630118611Snjl 631281075Sdim (AcpiUtAsciiCharToHex (InString[3])) << 12 | 632281075Sdim (AcpiUtAsciiCharToHex (InString[4])) << 8 | 633281075Sdim (AcpiUtAsciiCharToHex (InString[5])) << 4 | 634281075Sdim AcpiUtAsciiCharToHex (InString[6]); 635118611Snjl 636118611Snjl /* Swap to little-endian to get final ID (see function header) */ 637118611Snjl 638118611Snjl EisaId = AcpiUtDwordByteSwap (BigEndianId); 639118611Snjl } 640118611Snjl 641118611Snjl /* 642118611Snjl * Morph the Op into an integer, regardless of whether there 643118611Snjl * was an error in the EISAID string 644118611Snjl */ 645118611Snjl Op->Asl.Value.Integer = EisaId; 646118611Snjl 647118611Snjl Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; 648118611Snjl Op->Asl.ParseOpcode = PARSEOP_INTEGER; 649118611Snjl (void) OpcSetOptimalIntegerSize (Op); 650118611Snjl 651118611Snjl /* Op is now an integer */ 652118611Snjl 653118611Snjl UtSetParseOpName (Op); 654118611Snjl} 655118611Snjl 656118611Snjl 657118611Snjl/******************************************************************************* 658118611Snjl * 659228110Sjkim * FUNCTION: OpcDoUuId 660138287Smarks * 661281075Sdim * PARAMETERS: Op - Parse node 662138287Smarks * 663138287Smarks * RETURN: None 664138287Smarks * 665151937Sjkim * DESCRIPTION: Convert UUID string to 16-byte buffer 666138287Smarks * 667138287Smarks ******************************************************************************/ 668138287Smarks 669151937Sjkimstatic void 670138287SmarksOpcDoUuId ( 671138287Smarks ACPI_PARSE_OBJECT *Op) 672138287Smarks{ 673138287Smarks char *InString; 674281075Sdim UINT8 *Buffer; 675138287Smarks ACPI_STATUS Status = AE_OK; 676138287Smarks ACPI_PARSE_OBJECT *NewOp; 677138287Smarks 678138287Smarks 679281075Sdim InString = ACPI_CAST_PTR (char, Op->Asl.Value.String); 680138287Smarks Buffer = UtLocalCalloc (16); 681138287Smarks 682217365Sjkim Status = AuValidateUuid (InString); 683138287Smarks if (ACPI_FAILURE (Status)) 684138287Smarks { 685138287Smarks AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String); 686138287Smarks } 687217365Sjkim else 688138287Smarks { 689281075Sdim AcpiUtConvertStringToUuid (InString, Buffer); 690138287Smarks } 691138287Smarks 692138287Smarks /* Change Op to a Buffer */ 693138287Smarks 694138287Smarks Op->Asl.ParseOpcode = PARSEOP_BUFFER; 695138287Smarks Op->Common.AmlOpcode = AML_BUFFER_OP; 696151937Sjkim 697151937Sjkim /* Disable further optimization */ 698151937Sjkim 699151937Sjkim Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; 700138287Smarks UtSetParseOpName (Op); 701138287Smarks 702138287Smarks /* Child node is the buffer length */ 703138287Smarks 704138287Smarks NewOp = TrAllocateNode (PARSEOP_INTEGER); 705138287Smarks 706306536Sjkim NewOp->Asl.AmlOpcode = AML_BYTE_OP; 707138287Smarks NewOp->Asl.Value.Integer = 16; 708306536Sjkim NewOp->Asl.Parent = Op; 709138287Smarks 710138287Smarks Op->Asl.Child = NewOp; 711138287Smarks Op = NewOp; 712138287Smarks 713138287Smarks /* Peer to the child is the raw buffer data */ 714138287Smarks 715138287Smarks NewOp = TrAllocateNode (PARSEOP_RAW_DATA); 716306536Sjkim NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; 717306536Sjkim NewOp->Asl.AmlLength = 16; 718306536Sjkim NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer); 719306536Sjkim NewOp->Asl.Parent = Op->Asl.Parent; 720138287Smarks 721138287Smarks Op->Asl.Next = NewOp; 722138287Smarks} 723138287Smarks 724138287Smarks 725138287Smarks/******************************************************************************* 726138287Smarks * 727118611Snjl * FUNCTION: OpcGenerateAmlOpcode 728118611Snjl * 729281075Sdim * PARAMETERS: Op - Parse node 730118611Snjl * 731118611Snjl * RETURN: None 732118611Snjl * 733118611Snjl * DESCRIPTION: Generate the AML opcode associated with the node and its 734241973Sjkim * parse (lex/flex) keyword opcode. Essentially implements 735118611Snjl * a mapping between the parse opcodes and the actual AML opcodes. 736118611Snjl * 737118611Snjl ******************************************************************************/ 738118611Snjl 739118611Snjlvoid 740118611SnjlOpcGenerateAmlOpcode ( 741118611Snjl ACPI_PARSE_OBJECT *Op) 742118611Snjl{ 743118611Snjl UINT16 Index; 744118611Snjl 745118611Snjl 746118611Snjl Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE); 747118611Snjl 748118611Snjl Op->Asl.AmlOpcode = AslKeywordMapping[Index].AmlOpcode; 749118611Snjl Op->Asl.AcpiBtype = AslKeywordMapping[Index].AcpiBtype; 750118611Snjl Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags; 751118611Snjl 752118611Snjl if (!Op->Asl.Value.Integer) 753118611Snjl { 754118611Snjl Op->Asl.Value.Integer = AslKeywordMapping[Index].Value; 755118611Snjl } 756118611Snjl 757118611Snjl /* Special handling for some opcodes */ 758118611Snjl 759118611Snjl switch (Op->Asl.ParseOpcode) 760118611Snjl { 761118611Snjl case PARSEOP_INTEGER: 762118611Snjl /* 763118611Snjl * Set the opcode based on the size of the integer 764118611Snjl */ 765118611Snjl (void) OpcSetOptimalIntegerSize (Op); 766118611Snjl break; 767118611Snjl 768118611Snjl case PARSEOP_OFFSET: 769118611Snjl 770118611Snjl Op->Asl.AmlOpcodeLength = 1; 771118611Snjl break; 772118611Snjl 773118611Snjl case PARSEOP_ACCESSAS: 774118611Snjl 775118611Snjl OpcDoAccessAs (Op); 776118611Snjl break; 777118611Snjl 778228110Sjkim case PARSEOP_CONNECTION: 779228110Sjkim 780228110Sjkim OpcDoConnection (Op); 781228110Sjkim break; 782228110Sjkim 783118611Snjl case PARSEOP_EISAID: 784118611Snjl 785118611Snjl OpcDoEisaId (Op); 786118611Snjl break; 787118611Snjl 788281075Sdim case PARSEOP_PRINTF: 789281075Sdim 790281075Sdim OpcDoPrintf (Op); 791281075Sdim break; 792281075Sdim 793281075Sdim case PARSEOP_FPRINTF: 794281075Sdim 795281075Sdim OpcDoFprintf (Op); 796281075Sdim break; 797281075Sdim 798281075Sdim case PARSEOP_TOPLD: 799281075Sdim 800281075Sdim OpcDoPld (Op); 801281075Sdim break; 802281075Sdim 803138287Smarks case PARSEOP_TOUUID: 804138287Smarks 805138287Smarks OpcDoUuId (Op); 806138287Smarks break; 807138287Smarks 808118611Snjl case PARSEOP_UNICODE: 809118611Snjl 810118611Snjl OpcDoUnicode (Op); 811118611Snjl break; 812118611Snjl 813118611Snjl case PARSEOP_INCLUDE: 814118611Snjl 815118611Snjl Gbl_HasIncludeFiles = TRUE; 816118611Snjl break; 817118611Snjl 818118611Snjl case PARSEOP_EXTERNAL: 819118611Snjl 820306536Sjkim if (Gbl_DoExternals == FALSE) 821306536Sjkim { 822306536Sjkim Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 823306536Sjkim Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 824306536Sjkim } 825118611Snjl break; 826118611Snjl 827245582Sjkim case PARSEOP_TIMER: 828245582Sjkim 829245582Sjkim if (AcpiGbl_IntegerBitWidth == 32) 830245582Sjkim { 831245582Sjkim AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL); 832245582Sjkim } 833245582Sjkim break; 834245582Sjkim 835118611Snjl default: 836250838Sjkim 837118611Snjl /* Nothing to do for other opcodes */ 838250838Sjkim 839118611Snjl break; 840118611Snjl } 841118611Snjl 842118611Snjl return; 843118611Snjl} 844